diff --git a/api/go1.25.txt b/api/go1.25.txt deleted file mode 100644 index d50d19545f163a..00000000000000 --- a/api/go1.25.txt +++ /dev/null @@ -1,111 +0,0 @@ -pkg crypto, func SignMessage(Signer, io.Reader, []uint8, SignerOpts) ([]uint8, error) #63405 -pkg crypto, type MessageSigner interface { Public, Sign, SignMessage } #63405 -pkg crypto, type MessageSigner interface, Public() PublicKey #63405 -pkg crypto, type MessageSigner interface, Sign(io.Reader, []uint8, SignerOpts) ([]uint8, error) #63405 -pkg crypto, type MessageSigner interface, SignMessage(io.Reader, []uint8, SignerOpts) ([]uint8, error) #63405 -pkg crypto/ecdsa, func ParseRawPrivateKey(elliptic.Curve, []uint8) (*PrivateKey, error) #63963 -pkg crypto/ecdsa, func ParseUncompressedPublicKey(elliptic.Curve, []uint8) (*PublicKey, error) #63963 -pkg crypto/ecdsa, method (*PrivateKey) Bytes() ([]uint8, error) #63963 -pkg crypto/ecdsa, method (*PublicKey) Bytes() ([]uint8, error) #63963 -pkg crypto/sha3, method (*SHA3) Clone() (hash.Cloner, error) #69521 -pkg crypto/tls, type Config struct, GetEncryptedClientHelloKeys func(*ClientHelloInfo) ([]EncryptedClientHelloKey, error) #71920 -pkg crypto/tls, type ConnectionState struct, CurveID CurveID #67516 -pkg debug/elf, const PT_RISCV_ATTRIBUTES = 1879048195 #72843 -pkg debug/elf, const PT_RISCV_ATTRIBUTES ProgType #72843 -pkg debug/elf, const SHT_RISCV_ATTRIBUTES = 1879048195 #72843 -pkg debug/elf, const SHT_RISCV_ATTRIBUTES SectionType #72843 -pkg go/ast, const FilterFuncDuplicates //deprecated #73088 -pkg go/ast, const FilterImportDuplicates //deprecated #73088 -pkg go/ast, const FilterUnassociatedComments //deprecated #73088 -pkg go/ast, func FilterPackage //deprecated #73088 -pkg go/ast, func MergePackageFiles //deprecated #73088 -pkg go/ast, func PackageExports //deprecated #73088 -pkg go/ast, func PreorderStack(Node, []Node, func(Node, []Node) bool) #73319 -pkg go/ast, type MergeMode //deprecated #73088 -pkg go/parser, func ParseDir //deprecated #71122 -pkg go/token, method (*FileSet) AddExistingFiles(...*File) #73205 -pkg go/types, const FieldVar = 6 #70250 -pkg go/types, const FieldVar VarKind #70250 -pkg go/types, const LocalVar = 2 #70250 -pkg go/types, const LocalVar VarKind #70250 -pkg go/types, const PackageVar = 1 #70250 -pkg go/types, const PackageVar VarKind #70250 -pkg go/types, const ParamVar = 4 #70250 -pkg go/types, const ParamVar VarKind #70250 -pkg go/types, const RecvVar = 3 #70250 -pkg go/types, const RecvVar VarKind #70250 -pkg go/types, const ResultVar = 5 #70250 -pkg go/types, const ResultVar VarKind #70250 -pkg go/types, func LookupSelection(Type, bool, *Package, string) (Selection, bool) #70737 -pkg go/types, method (*Var) Kind() VarKind #70250 -pkg go/types, method (*Var) SetKind(VarKind) #70250 -pkg go/types, method (VarKind) String() string #70250 -pkg go/types, type VarKind uint8 #70250 -pkg hash, type Cloner interface { BlockSize, Clone, Reset, Size, Sum, Write } #69521 -pkg hash, type Cloner interface, BlockSize() int #69521 -pkg hash, type Cloner interface, Clone() (Cloner, error) #69521 -pkg hash, type Cloner interface, Reset() #69521 -pkg hash, type Cloner interface, Size() int #69521 -pkg hash, type Cloner interface, Sum([]uint8) []uint8 #69521 -pkg hash, type Cloner interface, Write([]uint8) (int, error) #69521 -pkg hash, type XOF interface { BlockSize, Read, Reset, Write } #69518 -pkg hash, type XOF interface, BlockSize() int #69518 -pkg hash, type XOF interface, Read([]uint8) (int, error) #69518 -pkg hash, type XOF interface, Reset() #69518 -pkg hash, type XOF interface, Write([]uint8) (int, error) #69518 -pkg hash/maphash, method (*Hash) Clone() (hash.Cloner, error) #69521 -pkg io/fs, func Lstat(FS, string) (FileInfo, error) #49580 -pkg io/fs, func ReadLink(FS, string) (string, error) #49580 -pkg io/fs, type ReadLinkFS interface { Lstat, Open, ReadLink } #49580 -pkg io/fs, type ReadLinkFS interface, Lstat(string) (FileInfo, error) #49580 -pkg io/fs, type ReadLinkFS interface, Open(string) (File, error) #49580 -pkg io/fs, type ReadLinkFS interface, ReadLink(string) (string, error) #49580 -pkg log/slog, func GroupAttrs(string, ...Attr) Attr #66365 -pkg log/slog, method (Record) Source() *Source #70280 -pkg mime/multipart, func FileContentDisposition(string, string) string #46771 -pkg net/http, func NewCrossOriginProtection() *CrossOriginProtection #73626 -pkg net/http, method (*CrossOriginProtection) AddInsecureBypassPattern(string) #73626 -pkg net/http, method (*CrossOriginProtection) AddTrustedOrigin(string) error #73626 -pkg net/http, method (*CrossOriginProtection) Check(*Request) error #73626 -pkg net/http, method (*CrossOriginProtection) Handler(Handler) Handler #73626 -pkg net/http, method (*CrossOriginProtection) SetDenyHandler(Handler) #73626 -pkg net/http, type CrossOriginProtection struct #73626 -pkg os, method (*Root) Chmod(string, fs.FileMode) error #67002 -pkg os, method (*Root) Chown(string, int, int) error #67002 -pkg os, method (*Root) Chtimes(string, time.Time, time.Time) error #67002 -pkg os, method (*Root) Lchown(string, int, int) error #67002 -pkg os, method (*Root) Link(string, string) error #67002 -pkg os, method (*Root) MkdirAll(string, fs.FileMode) error #67002 -pkg os, method (*Root) ReadFile(string) ([]uint8, error) #73126 -pkg os, method (*Root) Readlink(string) (string, error) #67002 -pkg os, method (*Root) RemoveAll(string) error #67002 -pkg os, method (*Root) Rename(string, string) error #67002 -pkg os, method (*Root) Symlink(string, string) error #67002 -pkg os, method (*Root) WriteFile(string, []uint8, fs.FileMode) error #73126 -pkg reflect, func TypeAssert[$0 interface{}](Value) ($0, bool) #62121 -pkg runtime, func SetDefaultGOMAXPROCS() #73193 -pkg runtime/trace, func NewFlightRecorder(FlightRecorderConfig) *FlightRecorder #63185 -pkg runtime/trace, method (*FlightRecorder) Enabled() bool #63185 -pkg runtime/trace, method (*FlightRecorder) Start() error #63185 -pkg runtime/trace, method (*FlightRecorder) Stop() #63185 -pkg runtime/trace, method (*FlightRecorder) WriteTo(io.Writer) (int64, error) #63185 -pkg runtime/trace, type FlightRecorder struct #63185 -pkg runtime/trace, type FlightRecorderConfig struct #63185 -pkg runtime/trace, type FlightRecorderConfig struct, MaxBytes uint64 #63185 -pkg runtime/trace, type FlightRecorderConfig struct, MinAge time.Duration #63185 -pkg sync, method (*WaitGroup) Go(func()) #63796 -pkg testing, method (*B) Attr(string, string) #43936 -pkg testing, method (*B) Output() io.Writer #59928 -pkg testing, method (*F) Attr(string, string) #43936 -pkg testing, method (*F) Output() io.Writer #59928 -pkg testing, method (*T) Attr(string, string) #43936 -pkg testing, method (*T) Output() io.Writer #59928 -pkg testing, type TB interface, Attr(string, string) #43936 -pkg testing, type TB interface, Output() io.Writer #59928 -pkg testing/fstest, method (MapFS) Lstat(string) (fs.FileInfo, error) #49580 -pkg testing/fstest, method (MapFS) ReadLink(string) (string, error) #49580 -pkg testing/synctest, func Test(*testing.T, func(*testing.T)) #67434 -pkg testing/synctest, func Wait() #67434 -pkg unicode, var CategoryAliases map[string]string #70780 -pkg unicode, var Cn *RangeTable #70780 -pkg unicode, var LC *RangeTable #70780 diff --git a/api/next/46771.txt b/api/next/46771.txt new file mode 100644 index 00000000000000..f7aad4b04aae6a --- /dev/null +++ b/api/next/46771.txt @@ -0,0 +1 @@ +pkg mime/multipart, func FileContentDisposition(string, string) string #46771 diff --git a/api/next/49580.txt b/api/next/49580.txt new file mode 100644 index 00000000000000..ce213cc9ca6816 --- /dev/null +++ b/api/next/49580.txt @@ -0,0 +1,8 @@ +pkg io/fs, func Lstat(FS, string) (FileInfo, error) #49580 +pkg io/fs, func ReadLink(FS, string) (string, error) #49580 +pkg io/fs, type ReadLinkFS interface { Lstat, Open, ReadLink } #49580 +pkg io/fs, type ReadLinkFS interface, Lstat(string) (FileInfo, error) #49580 +pkg io/fs, type ReadLinkFS interface, Open(string) (File, error) #49580 +pkg io/fs, type ReadLinkFS interface, ReadLink(string) (string, error) #49580 +pkg testing/fstest, method (MapFS) Lstat(string) (fs.FileInfo, error) #49580 +pkg testing/fstest, method (MapFS) ReadLink(string) (string, error) #49580 diff --git a/api/next/63796.txt b/api/next/63796.txt new file mode 100644 index 00000000000000..624ee9db3b1b85 --- /dev/null +++ b/api/next/63796.txt @@ -0,0 +1 @@ +pkg sync, method (*WaitGroup) Go(func()) #63769 diff --git a/api/next/67002.txt b/api/next/67002.txt new file mode 100644 index 00000000000000..112f477e8ec6c7 --- /dev/null +++ b/api/next/67002.txt @@ -0,0 +1,8 @@ +pkg os, method (*Root) Chmod(string, fs.FileMode) error #67002 +pkg os, method (*Root) Chown(string, int, int) error #67002 +pkg os, method (*Root) Chtimes(string, time.Time, time.Time) error #67002 +pkg os, method (*Root) Lchown(string, int, int) error #67002 +pkg os, method (*Root) Link(string, string) error #67002 +pkg os, method (*Root) Readlink(string) (string, error) #67002 +pkg os, method (*Root) Rename(string, string) error #67002 +pkg os, method (*Root) Symlink(string, string) error #67002 diff --git a/api/next/67516.txt b/api/next/67516.txt new file mode 100644 index 00000000000000..a9b6007d06a3d4 --- /dev/null +++ b/api/next/67516.txt @@ -0,0 +1 @@ +pkg crypto/tls, type ConnectionState struct, CurveID CurveID #67516 diff --git a/api/next/70250.txt b/api/next/70250.txt new file mode 100644 index 00000000000000..faad356cefbb4a --- /dev/null +++ b/api/next/70250.txt @@ -0,0 +1,17 @@ +pkg go/types, const FieldVar = 6 #70250 +pkg go/types, const FieldVar VarKind #70250 +pkg go/types, const LocalVar = 2 #70250 +pkg go/types, const LocalVar VarKind #70250 +pkg go/types, const PackageVar = 1 #70250 +pkg go/types, const PackageVar VarKind #70250 +pkg go/types, const ParamVar = 4 #70250 +pkg go/types, const ParamVar VarKind #70250 +pkg go/types, const RecvVar = 3 #70250 +pkg go/types, const RecvVar VarKind #70250 +pkg go/types, const ResultVar = 5 #70250 +pkg go/types, const ResultVar VarKind #70250 +pkg go/types, func LookupSelection(Type, bool, *Package, string) (Selection, bool) #70737 +pkg go/types, method (*Var) Kind() VarKind #70250 +pkg go/types, method (*Var) SetKind(VarKind) #70250 +pkg go/types, method (VarKind) String() string #70250 +pkg go/types, type VarKind uint8 #70250 diff --git a/api/next/71122.txt b/api/next/71122.txt new file mode 100644 index 00000000000000..a679899e0ccdd5 --- /dev/null +++ b/api/next/71122.txt @@ -0,0 +1 @@ +pkg go/parser, func ParseDir //deprecated #71122 diff --git a/api/next/72843.txt b/api/next/72843.txt new file mode 100644 index 00000000000000..efd45ccc6f5c86 --- /dev/null +++ b/api/next/72843.txt @@ -0,0 +1,4 @@ +pkg debug/elf, const PT_RISCV_ATTRIBUTES = 1879048195 #72843 +pkg debug/elf, const PT_RISCV_ATTRIBUTES ProgType #72843 +pkg debug/elf, const SHT_RISCV_ATTRIBUTES = 1879048195 #72843 +pkg debug/elf, const SHT_RISCV_ATTRIBUTES SectionType #72843 diff --git a/doc/go_spec.html b/doc/go_spec.html index 183bc7fb372755..479605e36c1bdb 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -7894,7 +7894,7 @@
The protect
function in the example below invokes
the function argument g
and protects callers from
-run-time panics caused by g
.
+run-time panics raised by g
.
diff --git a/doc/godebug.md b/doc/godebug.md index 15be9da5df0acb..f3ad820d3cddea 100644 --- a/doc/godebug.md +++ b/doc/godebug.md @@ -169,26 +169,6 @@ Go command will follow symlinks to regular files embedding files. The default value `embedfollowsymlinks=0` does not allow following symlinks. `embedfollowsymlinks=1` will allow following symlinks. -Go 1.25 added a new `containermaxprocs` setting that controls whether the Go -runtime will consider cgroup CPU limits when setting the default GOMAXPROCS. -The default value `containermaxprocs=1` will use cgroup limits in addition to -the total logical CPU count and CPU affinity. `containermaxprocs=0` will -disable consideration of cgroup limits. This setting only affects Linux. - -Go 1.25 added a new `updatemaxprocs` setting that controls whether the Go -runtime will periodically update GOMAXPROCS for new CPU affinity or cgroup -limits. The default value `updatemaxprocs=1` will enable periodic updates. -`updatemaxprocs=0` will disable periodic updates. - -Go 1.25 disabled SHA-1 signature algorithms in TLS 1.2 according to RFC 9155. -The default can be reverted using the `tlssha1=1` setting. - -Go 1.25 switched to SHA-256 to fill in missing SubjectKeyId in -crypto/x509.CreateCertificate. The setting `x509sha256skid=0` reverts to SHA-1. - -Go 1.25 corrected the semantics of contention reports for runtime-internal locks, -and so removed the [`runtimecontentionstacks` setting](/pkg/runtime#hdr-Environment_Variable). - ### Go 1.24 Go 1.24 added a new `fips140` setting that controls whether the Go @@ -390,7 +370,7 @@ certificate policy OIDs with components larger than 31 bits. By default this field is only used during parsing, when it is populated with policy OIDs, but not used during marshaling. It can be used to marshal these larger OIDs, instead of the existing PolicyIdentifiers field, by using the -[`x509usepolicies` setting](/pkg/crypto/x509/#CreateCertificate). +[`x509usepolicies` setting.](/pkg/crypto/x509/#CreateCertificate). ### Go 1.21 diff --git a/doc/next/1-intro.md b/doc/next/1-intro.md new file mode 100644 index 00000000000000..77a9aed59f244c --- /dev/null +++ b/doc/next/1-intro.md @@ -0,0 +1,8 @@ + + +## DRAFT RELEASE NOTES — Introduction to Go 1.N {#introduction} + +**Go 1.25 is not yet released. These are work-in-progress release notes. +Go 1.25 is expected to be released in August 2025.** diff --git a/doc/next/2-language.md b/doc/next/2-language.md new file mode 100644 index 00000000000000..61030bd67606b0 --- /dev/null +++ b/doc/next/2-language.md @@ -0,0 +1,3 @@ +## Changes to the language {#language} + + diff --git a/doc/next/3-tools.md b/doc/next/3-tools.md new file mode 100644 index 00000000000000..886852b784eacf --- /dev/null +++ b/doc/next/3-tools.md @@ -0,0 +1,35 @@ +## Tools {#tools} + +### Go command {#go-command} + +The `go build` `-asan` option now defaults to doing leak detection at +program exit. +This will report an error if memory allocated by C is not freed and is +not referenced by any other memory allocated by either C or Go. +These new error reports may be disabled by setting +`ASAN_OPTIONS=detect_leaks=0` in the environment when running the +program. + + + +The new `work` package pattern matches all packages in the work (formerly called main) +modules: either the single work module in module mode or the set of workspace modules +in workspace mode. + + + +When the go command updates the `go` line in a `go.mod` or `go.work` file, +it [no longer](/ref/mod#go-mod-file-toolchain) adds a toolchain line +specifying the command's current version. + +### Cgo {#cgo} + +### Vet {#vet} + + + +The `go vet` command now includes the +[waitgroup](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/waitgroup) +analyzer, which reports misplaced calls to [sync.WaitGroup.Add]. + + diff --git a/doc/next/4-runtime.md b/doc/next/4-runtime.md new file mode 100644 index 00000000000000..b6b50f1c0a755f --- /dev/null +++ b/doc/next/4-runtime.md @@ -0,0 +1,26 @@ +## Runtime {#runtime} + + + +The message printed when a program exits due to an unhandled panic +that was recovered and re-raised no longer repeats the text of +the panic value. + +Previously, a program which panicked with `panic("PANIC")`, +recovered the panic, and then re-panicked with the original +value would print: + + panic: PANIC [recovered] + panic: PANIC + +This program will now print: + + panic: PANIC [recovered, reraised] + + + +On Linux systems with kernel support for anonymous VMA names +(`CONFIG_ANON_VMA_NAME`), the Go runtime will annotate anonymous memory +mappings with context about their purpose. e.g., `[anon: Go: heap]` for heap +memory. This can be disabled with the [GODEBUG setting](/doc/godebug) +`decoratemappings=0`. diff --git a/doc/next/5-toolchain.md b/doc/next/5-toolchain.md new file mode 100644 index 00000000000000..c4d4744168d780 --- /dev/null +++ b/doc/next/5-toolchain.md @@ -0,0 +1,44 @@ +## Compiler {#compiler} + + + +The compiler and linker in Go 1.25 now generate debug information +using [DWARF version 5](https://dwarfstd.org/dwarf5std.html); the +newer DWARF version reduces the space required for debuging +information in Go binaries. +DWARF 5 generation is gated by the "dwarf5" GOEXPERIMENT; this +functionality can be disabled (for now) using GOEXPERIMENT=nodwarf5. + + + +The compiler [has been fixed](/cl/657715) +to ensure that nil pointer checks are performed promptly. Programs like the following, +which used to execute successfully, will now panic with a nil-pointer exception: + +``` +package main + +import "os" + +func main() { + f, err := os.Open("nonExistentFile") + name := f.Name() + if err != nil { + return + } + println(name) +} +``` + +This program is incorrect in that it uses the result of `os.Open` before checking +the error. The main result of `os.Open` can be a nil pointer if the error result is non-nil. +But because of [a compiler bug](/issue/72860), this program ran successfully under +Go versions 1.21 through 1.24 (in violation of the Go spec). It will no longer run +successfully in Go 1.25. If this change is affecting your code, the solution is to put +the non-nil error check earlier in your code, preferrably immediately after +the error-generating statement. + +## Assembler {#assembler} + +## Linker {#linker} + diff --git a/doc/next/6-stdlib/0-heading.md b/doc/next/6-stdlib/0-heading.md new file mode 100644 index 00000000000000..a992170d433326 --- /dev/null +++ b/doc/next/6-stdlib/0-heading.md @@ -0,0 +1,2 @@ +## Standard library {#library} + diff --git a/doc/next/6-stdlib/99-minor/0-heading.md b/doc/next/6-stdlib/99-minor/0-heading.md new file mode 100644 index 00000000000000..a98105e8ccba7f --- /dev/null +++ b/doc/next/6-stdlib/99-minor/0-heading.md @@ -0,0 +1,3 @@ +### Minor changes to the library {#minor_library_changes} + + diff --git a/doc/next/6-stdlib/99-minor/README b/doc/next/6-stdlib/99-minor/README new file mode 100644 index 00000000000000..fac778de050642 --- /dev/null +++ b/doc/next/6-stdlib/99-minor/README @@ -0,0 +1 @@ +API changes and other small changes to the standard library go here. diff --git a/doc/next/6-stdlib/99-minor/archive/tar/49580.md b/doc/next/6-stdlib/99-minor/archive/tar/49580.md new file mode 100644 index 00000000000000..8fa43681fa4163 --- /dev/null +++ b/doc/next/6-stdlib/99-minor/archive/tar/49580.md @@ -0,0 +1,2 @@ +The [*Writer.AddFS] implementation now supports symbolic links +for filesystems that implement [io/fs.ReadLinkFS]. diff --git a/doc/next/6-stdlib/99-minor/crypto/elliptic/hidden.md b/doc/next/6-stdlib/99-minor/crypto/elliptic/hidden.md new file mode 100644 index 00000000000000..eb3bef50d3babb --- /dev/null +++ b/doc/next/6-stdlib/99-minor/crypto/elliptic/hidden.md @@ -0,0 +1,2 @@ +The hidden and undocumented `Inverse` and `CombinedMult` methods on some [Curve] +implementations have been removed. diff --git a/doc/next/6-stdlib/99-minor/crypto/tls/67516.md b/doc/next/6-stdlib/99-minor/crypto/tls/67516.md new file mode 100644 index 00000000000000..3790533d16f86d --- /dev/null +++ b/doc/next/6-stdlib/99-minor/crypto/tls/67516.md @@ -0,0 +1,2 @@ +The new [ConnectionState.CurveID] field exposes the key exchange mechanism used +to establish the connection. diff --git a/doc/next/6-stdlib/99-minor/crypto/tls/fips.md b/doc/next/6-stdlib/99-minor/crypto/tls/fips.md new file mode 100644 index 00000000000000..0f0c9459cee0c2 --- /dev/null +++ b/doc/next/6-stdlib/99-minor/crypto/tls/fips.md @@ -0,0 +1,2 @@ +When [FIPS 140-3 mode](/doc/security/fips140) is enabled, Extended Master Secret +is now required in TLS 1.2, and Ed25519 and X25519MLKEM768 are now allowed. diff --git a/doc/next/6-stdlib/99-minor/debug/elf/72843.md b/doc/next/6-stdlib/99-minor/debug/elf/72843.md new file mode 100644 index 00000000000000..491c2dc1a11d53 --- /dev/null +++ b/doc/next/6-stdlib/99-minor/debug/elf/72843.md @@ -0,0 +1,4 @@ +The [debug/elf] package adds two new constants: +- [PT_RISCV_ATTRIBUTES] +- [SHT_RISCV_ATTRIBUTES] +for RISC-V ELF parsing. diff --git a/doc/next/6-stdlib/99-minor/go/parser/71122.md b/doc/next/6-stdlib/99-minor/go/parser/71122.md new file mode 100644 index 00000000000000..2043d3040366eb --- /dev/null +++ b/doc/next/6-stdlib/99-minor/go/parser/71122.md @@ -0,0 +1 @@ +The [ParseDir] function is deprecated. diff --git a/doc/next/6-stdlib/99-minor/go/types/70250.md b/doc/next/6-stdlib/99-minor/go/types/70250.md new file mode 100644 index 00000000000000..49fbdadfe91282 --- /dev/null +++ b/doc/next/6-stdlib/99-minor/go/types/70250.md @@ -0,0 +1,3 @@ +[Var] now has a [Var.Kind] method that classifies the variable as one +of: package-level, receiver, parameter, result, or local variable, or +a struct field. diff --git a/doc/next/6-stdlib/99-minor/go/types/70737.md b/doc/next/6-stdlib/99-minor/go/types/70737.md new file mode 100644 index 00000000000000..6d1b4136bf03ab --- /dev/null +++ b/doc/next/6-stdlib/99-minor/go/types/70737.md @@ -0,0 +1,3 @@ +The new [LookupSelection] function looks up the field or method of a +given name and receiver type, like the existing [LookupFieldOrMethod] +function, but returns the result in the form of a [Selection]. diff --git a/doc/next/6-stdlib/99-minor/io/fs/49580.md b/doc/next/6-stdlib/99-minor/io/fs/49580.md new file mode 100644 index 00000000000000..c1cba5a3957dcb --- /dev/null +++ b/doc/next/6-stdlib/99-minor/io/fs/49580.md @@ -0,0 +1 @@ +A new [ReadLinkFS] interface provides the ability to read symbolic links in a filesystem. diff --git a/doc/next/6-stdlib/99-minor/mime/multipart/46771.md b/doc/next/6-stdlib/99-minor/mime/multipart/46771.md new file mode 100644 index 00000000000000..b8b8641b7848e6 --- /dev/null +++ b/doc/next/6-stdlib/99-minor/mime/multipart/46771.md @@ -0,0 +1,2 @@ +The new helper function [FieldContentDisposition] builds multipart +Content-Disposition header fields. \ No newline at end of file diff --git a/doc/next/6-stdlib/99-minor/net/56025.md b/doc/next/6-stdlib/99-minor/net/56025.md new file mode 100644 index 00000000000000..2e3b230ef01cd3 --- /dev/null +++ b/doc/next/6-stdlib/99-minor/net/56025.md @@ -0,0 +1,5 @@ +[LookupMX] and [*Resolver.LookupMX] now return DNS names that look +like valid IP address, as well as valid domain names. +Previously if a name server returned an IP address as a DNS name, +LookupMX would discard it, as required by the RFCs. +However, name servers in practice do sometimes return IP addresses. diff --git a/doc/next/6-stdlib/99-minor/os/15388.md b/doc/next/6-stdlib/99-minor/os/15388.md new file mode 100644 index 00000000000000..04b3e91d8bb7e2 --- /dev/null +++ b/doc/next/6-stdlib/99-minor/os/15388.md @@ -0,0 +1,14 @@ +On Windows, [NewFile] now supports handles opened for asynchronous I/O (that is, +[syscall.FILE_FLAG_OVERLAPPED] is specified in the [syscall.CreateFile] call). +These handles are associated with the Go runtime's I/O completion port, +which provides the following benefits for the resulting [File]: + +- I/O methods ([File.Read], [File.Write], [File.ReadAt], and [File.WriteAt]) do not block an OS thread. +- Deadline methods ([File.SetDeadline], [File.SetReadDeadline], and [File.SetWriteDeadline]) are supported. + +This enhancement is especially beneficial for applications that communicate via named pipes on Windows. + +Note that a handle can only be associated with one completion port at a time. +If the handle provided to [NewFile] is already associated with a completion port, +the returned [File] is downgraded to synchronous I/O mode. +In this case, I/O methods will block an OS thread, and the deadline methods have no effect. diff --git a/doc/next/6-stdlib/99-minor/os/49580.md b/doc/next/6-stdlib/99-minor/os/49580.md new file mode 100644 index 00000000000000..18d8831e7be6ef --- /dev/null +++ b/doc/next/6-stdlib/99-minor/os/49580.md @@ -0,0 +1,2 @@ +The filesystem returned by [DirFS] implements the new [io/fs.ReadLinkFS] interface. +[CopyFS] supports symlinks when copying filesystems that implement [io/fs.ReadLinkFS]. diff --git a/doc/next/6-stdlib/99-minor/os/67002.md b/doc/next/6-stdlib/99-minor/os/67002.md new file mode 100644 index 00000000000000..84661c6c407579 --- /dev/null +++ b/doc/next/6-stdlib/99-minor/os/67002.md @@ -0,0 +1,10 @@ +The [os.Root] type supports the following additional methods: + + * [os.Root.Chmod] + * [os.Root.Chown] + * [os.Root.Chtimes] + * [os.Root.Lchown] + * [os.Root.Link] + * [os.Root.Readlink] + * [os.Root.Rename] + * [os.Root.Symlink] diff --git a/doc/next/6-stdlib/99-minor/sync/63769.md b/doc/next/6-stdlib/99-minor/sync/63769.md new file mode 100644 index 00000000000000..60d91a949a04e4 --- /dev/null +++ b/doc/next/6-stdlib/99-minor/sync/63769.md @@ -0,0 +1,2 @@ +[WaitGroup] has added a new method [WaitGroup.Go], +that makes the common pattern of creating and counting goroutines more convenient. diff --git a/doc/next/6-stdlib/99-minor/testing/fstest/49580.md b/doc/next/6-stdlib/99-minor/testing/fstest/49580.md new file mode 100644 index 00000000000000..5b3c0d6a84eb22 --- /dev/null +++ b/doc/next/6-stdlib/99-minor/testing/fstest/49580.md @@ -0,0 +1,3 @@ +[MapFS] implements the new [io/fs.ReadLinkFS] interface. +[TestFS] will verify the functionality of the [io/fs.ReadLinkFS] interface if implemented. +[TestFS] will no longer follow symlinks to avoid unbounded recursion. diff --git a/doc/next/7-ports.md b/doc/next/7-ports.md new file mode 100644 index 00000000000000..eb4f0d5a9703c4 --- /dev/null +++ b/doc/next/7-ports.md @@ -0,0 +1,11 @@ +## Ports {#ports} + +### Darwin + + +As [announced](/doc/go1.24#darwin) in the Go 1.24 release notes, Go 1.25 requires macOS 12 Monterey or later; support for previous versions has been discontinued. + +### Windows + + +Go 1.25 is the last release that contains the [broken](/doc/go1.24#windows) 32-bit windows/arm port (`GOOS=windows` `GOARCH=arm`). It will be removed in Go 1.26. diff --git a/lib/fips140/inprocess.txt b/lib/fips140/inprocess.txt deleted file mode 100644 index 0ec25f7505c14b..00000000000000 --- a/lib/fips140/inprocess.txt +++ /dev/null @@ -1 +0,0 @@ -v1.0.0 diff --git a/lib/time/update.bash b/lib/time/update.bash index 66494752ea3c4b..940596fb11221f 100755 --- a/lib/time/update.bash +++ b/lib/time/update.bash @@ -24,8 +24,8 @@ # in the CL match the update.bash in the CL. # Versions to use. -CODE=2025b -DATA=2025b +CODE=2025a +DATA=2025a set -e diff --git a/lib/time/zoneinfo.zip b/lib/time/zoneinfo.zip index b107695d1ef042..f8099b1b494fc9 100644 Binary files a/lib/time/zoneinfo.zip and b/lib/time/zoneinfo.zip differ diff --git a/src/all.bash b/src/all.bash index adbc60e361f4a6..1b8ca093e45896 100755 --- a/src/all.bash +++ b/src/all.bash @@ -10,4 +10,4 @@ if [ ! -f make.bash ]; then fi . ./make.bash "$@" --no-banner bash run.bash --no-rebuild -../bin/go tool dist banner # print build info +"$GOTOOLDIR/dist" banner # print build info diff --git a/src/all.rc b/src/all.rc index ad8c3e143e5349..45b1261a2064a6 100755 --- a/src/all.rc +++ b/src/all.rc @@ -13,4 +13,4 @@ if(! test -f make.rc){ . ./make.rc --no-banner $* bind -b $GOROOT/bin /bin ./run.rc --no-rebuild -../bin/go tool dist banner # print build info +$GOTOOLDIR/dist banner # print build info diff --git a/src/bufio/scan.go b/src/bufio/scan.go index 1a0a3907c9eb85..a26b2ff17d3a26 100644 --- a/src/bufio/scan.go +++ b/src/bufio/scan.go @@ -260,11 +260,8 @@ func (s *Scanner) setErr(err error) { } } -// Buffer controls memory allocation by the Scanner. -// It sets the initial buffer to use when scanning +// Buffer sets the initial buffer to use when scanning // and the maximum size of buffer that may be allocated during scanning. -// The contents of the buffer are ignored. -// // The maximum token size must be less than the larger of max and cap(buf). // If max <= cap(buf), [Scanner.Scan] will use this buffer only and do no allocation. // diff --git a/src/bytes/buffer.go b/src/bytes/buffer.go index 9684513942da88..f90d9eca0fe496 100644 --- a/src/bytes/buffer.go +++ b/src/bytes/buffer.go @@ -21,12 +21,6 @@ type Buffer struct { buf []byte // contents are the bytes buf[off : len(buf)] off int // read at &buf[off], write at &buf[len(buf)] lastRead readOp // last read operation, so that Unread* can work correctly. - - // Copying and modifying a non-zero Buffer is prone to error, - // but we cannot employ the noCopy trick used by WaitGroup and Mutex, - // which causes vet's copylocks checker to report misuse, as vet - // cannot reliably distinguish the zero and non-zero cases. - // See #26462, #25907, #47276, #48398 for history. } // The readOp constants describe the last action performed on diff --git a/src/bytes/buffer_test.go b/src/bytes/buffer_test.go index b46ba1204eb806..97fca5a9d136f9 100644 --- a/src/bytes/buffer_test.go +++ b/src/bytes/buffer_test.go @@ -354,7 +354,7 @@ func TestWriteAppend(t *testing.T) { got.Write(b) } if !Equal(got.Bytes(), want) { - t.Fatalf("Bytes() = %q, want %q", &got, want) + t.Fatalf("Bytes() = %q, want %q", got, want) } // With a sufficiently sized buffer, there should be no allocations. diff --git a/src/bytes/bytes.go b/src/bytes/bytes.go index a0a8fa0b2986e1..8198415c3e1938 100644 --- a/src/bytes/bytes.go +++ b/src/bytes/bytes.go @@ -1228,7 +1228,7 @@ func ReplaceAll(s, old, new []byte) []byte { func EqualFold(s, t []byte) bool { // ASCII fast path i := 0 - for n := min(len(s), len(t)); i < n; i++ { + for ; i < len(s) && i < len(t); i++ { sr := s[i] tr := t[i] if sr|tr >= utf8.RuneSelf { diff --git a/src/bytes/bytes_test.go b/src/bytes/bytes_test.go index 0f6cf4993af642..14b52a80358bb7 100644 --- a/src/bytes/bytes_test.go +++ b/src/bytes/bytes_test.go @@ -2128,9 +2128,8 @@ func TestContainsFunc(t *testing.T) { var makeFieldsInput = func() []byte { x := make([]byte, 1<<20) // Input is ~10% space, ~10% 2-byte UTF-8, rest ASCII non-space. - r := rand.New(rand.NewSource(99)) for i := range x { - switch r.Intn(10) { + switch rand.Intn(10) { case 0: x[i] = ' ' case 1: @@ -2149,9 +2148,8 @@ var makeFieldsInput = func() []byte { var makeFieldsInputASCII = func() []byte { x := make([]byte, 1<<20) // Input is ~10% space, rest ASCII non-space. - r := rand.New(rand.NewSource(99)) for i := range x { - if r.Intn(10) == 0 { + if rand.Intn(10) == 0 { x[i] = ' ' } else { x[i] = 'x' @@ -2248,9 +2246,8 @@ func makeBenchInputHard() []byte { "hello", "world", } x := make([]byte, 0, 1<<20) - r := rand.New(rand.NewSource(99)) for { - i := r.Intn(len(tokens)) + i := rand.Intn(len(tokens)) if len(x)+len(tokens[i]) >= 1<<20 { break } diff --git a/src/bytes/example_test.go b/src/bytes/example_test.go index c489b950e59a91..71a4a9e2ca2f23 100644 --- a/src/bytes/example_test.go +++ b/src/bytes/example_test.go @@ -245,9 +245,9 @@ func ExampleCut() { } func ExampleCutPrefix() { - show := func(s, prefix string) { - after, found := bytes.CutPrefix([]byte(s), []byte(prefix)) - fmt.Printf("CutPrefix(%q, %q) = %q, %v\n", s, prefix, after, found) + show := func(s, sep string) { + after, found := bytes.CutPrefix([]byte(s), []byte(sep)) + fmt.Printf("CutPrefix(%q, %q) = %q, %v\n", s, sep, after, found) } show("Gopher", "Go") show("Gopher", "ph") @@ -257,9 +257,9 @@ func ExampleCutPrefix() { } func ExampleCutSuffix() { - show := func(s, suffix string) { - before, found := bytes.CutSuffix([]byte(s), []byte(suffix)) - fmt.Printf("CutSuffix(%q, %q) = %q, %v\n", s, suffix, before, found) + show := func(s, sep string) { + before, found := bytes.CutSuffix([]byte(s), []byte(sep)) + fmt.Printf("CutSuffix(%q, %q) = %q, %v\n", s, sep, before, found) } show("Gopher", "Go") show("Gopher", "er") diff --git a/src/bytes/iter.go b/src/bytes/iter.go index b2abb2c9ba3dc6..8e9ee8b98d88db 100644 --- a/src/bytes/iter.go +++ b/src/bytes/iter.go @@ -31,20 +31,26 @@ func Lines(s []byte) iter.Seq[[]byte] { } } +// explodeSeq returns an iterator over the runes in s. +func explodeSeq(s []byte) iter.Seq[[]byte] { + return func(yield func([]byte) bool) { + for len(s) > 0 { + _, size := utf8.DecodeRune(s) + if !yield(s[:size:size]) { + return + } + s = s[size:] + } + } +} + // splitSeq is SplitSeq or SplitAfterSeq, configured by how many // bytes of sep to include in the results (none or all). func splitSeq(s, sep []byte, sepSave int) iter.Seq[[]byte] { + if len(sep) == 0 { + return explodeSeq(s) + } return func(yield func([]byte) bool) { - if len(sep) == 0 { - for len(s) > 0 { - _, size := utf8.DecodeRune(s) - if !yield(s[:size:size]) { - return - } - s = s[size:] - } - return - } for { i := Index(s, sep) if i < 0 { diff --git a/src/bytes/iter_test.go b/src/bytes/iter_test.go deleted file mode 100644 index e37fdfb96d1b61..00000000000000 --- a/src/bytes/iter_test.go +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2024 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 bytes_test - -import ( - . "bytes" - "testing" -) - -func BenchmarkSplitSeqEmptySeparator(b *testing.B) { - for range b.N { - for range SplitSeq(benchInputHard, nil) { - } - } -} - -func BenchmarkSplitSeqSingleByteSeparator(b *testing.B) { - sep := []byte("/") - for range b.N { - for range SplitSeq(benchInputHard, sep) { - } - } -} - -func BenchmarkSplitSeqMultiByteSeparator(b *testing.B) { - sep := []byte("hello") - for range b.N { - for range SplitSeq(benchInputHard, sep) { - } - } -} - -func BenchmarkSplitAfterSeqEmptySeparator(b *testing.B) { - for range b.N { - for range SplitAfterSeq(benchInputHard, nil) { - } - } -} - -func BenchmarkSplitAfterSeqSingleByteSeparator(b *testing.B) { - sep := []byte("/") - for range b.N { - for range SplitAfterSeq(benchInputHard, sep) { - } - } -} - -func BenchmarkSplitAfterSeqMultiByteSeparator(b *testing.B) { - sep := []byte("hello") - for range b.N { - for range SplitAfterSeq(benchInputHard, sep) { - } - } -} diff --git a/src/cmd/api/api_test.go b/src/cmd/api/api_test.go index 98ebf168ef3949..32da68982bce45 100644 --- a/src/cmd/api/api_test.go +++ b/src/cmd/api/api_test.go @@ -99,11 +99,6 @@ func TestGolden(t *testing.T) { } func TestCompareAPI(t *testing.T) { - if *flagCheck { - // not worth repeating in -check - t.Skip("skipping with -check set") - } - tests := []struct { name string features, required, exception []string @@ -185,11 +180,6 @@ func TestCompareAPI(t *testing.T) { } func TestSkipInternal(t *testing.T) { - if *flagCheck { - // not worth repeating in -check - t.Skip("skipping with -check set") - } - tests := []struct { pkg string want bool @@ -304,20 +294,14 @@ func TestIssue41358(t *testing.T) { } func TestIssue64958(t *testing.T) { - if testing.Short() { - t.Skip("skipping with -short") - } - if *flagCheck { - // slow, not worth repeating in -check - t.Skip("skipping with -check set") - } - testenv.MustHaveGoBuild(t) - defer func() { if x := recover(); x != nil { t.Errorf("expected no panic; recovered %v", x) } }() + + testenv.MustHaveGoBuild(t) + for _, context := range contexts { w := NewWalker(context, "testdata/src/issue64958") pkg, err := w.importFrom("p", "", 0) diff --git a/src/cmd/asm/internal/arch/loong64.go b/src/cmd/asm/internal/arch/loong64.go index bf5175f4a0bad6..d9e428d953bb99 100644 --- a/src/cmd/asm/internal/arch/loong64.go +++ b/src/cmd/asm/internal/arch/loong64.go @@ -46,14 +46,6 @@ func IsLoong64RDTIME(op obj.As) bool { return false } -func IsLoong64PRELD(op obj.As) bool { - switch op { - case loong64.APRELD, loong64.APRELDX: - return true - } - return false -} - func IsLoong64AMO(op obj.As) bool { return loong64.IsAtomicInst(op) } diff --git a/src/cmd/asm/internal/asm/asm.go b/src/cmd/asm/internal/asm/asm.go index 9a6e22cab2c282..a1f6a73d708103 100644 --- a/src/cmd/asm/internal/asm/asm.go +++ b/src/cmd/asm/internal/asm/asm.go @@ -654,12 +654,6 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) { prog.RegTo2 = a[1].Reg break } - - if arch.IsLoong64PRELD(op) { - prog.From = a[0] - prog.AddRestSource(a[1]) - break - } } prog.From = a[0] prog.To = a[1] @@ -676,11 +670,6 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) { prog.From = a[0] prog.To = a[1] prog.RegTo2 = a[2].Reg - - case arch.IsLoong64PRELD(op): - prog.From = a[0] - prog.AddRestSourceArgs([]obj.Addr{a[1], a[2]}) - default: prog.From = a[0] prog.Reg = p.getRegister(prog, op, &a[1]) diff --git a/src/cmd/asm/internal/asm/testdata/loong64enc1.s b/src/cmd/asm/internal/asm/testdata/loong64enc1.s index bfff555782e9f7..ad0ffa33d68c7b 100644 --- a/src/cmd/asm/internal/asm/testdata/loong64enc1.s +++ b/src/cmd/asm/internal/asm/testdata/loong64enc1.s @@ -6,16 +6,12 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0 lable1: - BFPT 1(PC) // 00050048 - BFPT lable1 // BFPT 2 // 1ffdff4b - BFPT FCC0, lable1 // BFPT FCC0, 2 // 1ff9ff4b - BFPT FCC7, lable1 // BFPT FCC7, 2 // fff5ff4b + BFPT 1(PC) // 00050048 + BFPT lable1 // BFPT 2 //1ffdff4b lable2: - BFPF 1(PC) // 00040048 - BFPF lable2 // BFPF 6 // 1ffcff4b - BFPF FCC0, lable2 // BFPF FCC0, 6 // 1ff8ff4b - BFPF FCC7, lable2 // BFPF FCC7, 6 // fff4ff4b + BFPF 1(PC) // 00040048 + BFPF lable2 // BFPF 4 // 1ffcff4b // relocation in play so the assembled offset should be 0 JMP foo(SB) // 00000050 @@ -547,22 +543,12 @@ lable2: VNORV V1, V2, V3 // 43842771 VANDNV V1, V2, V3 // 43042871 VORNV V1, V2, V3 // 43842871 - VANDV V1, V2 // 42042671 - VORV V1, V2 // 42842671 - VXORV V1, V2 // 42042771 - VNORV V1, V2 // 42842771 - VANDNV V1, V2 // 42042871 - VORNV V1, V2 // 42842871 // VANDB,VORB,VXORB,VNORB VANDB $0, V2, V3 // 4300d073 VORB $64, V2, V3 // 4300d573 VXORB $128, V2, V3 // 4300da73 VNORB $255, V2, V3 // 43fcdf73 - VANDB $0, V2 // 4200d073 - VORB $64, V2 // 4200d573 - VXORB $128, V2 // 4200da73 - VNORB $255, V2 // 42fcdf73 // XVANDV,XVORV,XVXORV,XVNORV,XVANDNV,XVORNV XVANDV X1, X2, X3 // 43042675 @@ -571,22 +557,12 @@ lable2: XVNORV X1, X2, X3 // 43842775 XVANDNV X1, X2, X3 // 43042875 XVORNV X1, X2, X3 // 43842875 - XVANDV X1, X2 // 42042675 - XVORV X1, X2 // 42842675 - XVXORV X1, X2 // 42042775 - XVNORV X1, X2 // 42842775 - XVANDNV X1, X2 // 42042875 - XVORNV X1, X2 // 42842875 // XVANDB,XVORB,XVXORB,XVNORB XVANDB $0, X2, X3 // 4300d077 XVORB $1, X2, X3 // 4304d477 XVXORB $127, X2, X3 // 43fcd977 XVNORB $255, X2, X3 // 43fcdf77 - XVANDB $0, X2 // 4200d077 - XVORB $1, X2 // 4204d477 - XVXORB $127, X2 // 42fcd977 - XVNORB $255, X2 // 42fcdf77 // MOVV C_DCON12_0, r MOVV $0x7a90000000000000, R4 // MOVV $8831558869273542656, R4 // 04a41e03 @@ -984,54 +960,3 @@ lable2: XVSETALLNEH X1, FCC0 // 20b49c76 XVSETALLNEW X1, FCC0 // 20b89c76 XVSETALLNEV X1, FCC0 // 20bc9c76 - - // [X]VFRINT[{RNE/RZ/RP/RM}].{S/D} instructions - VFRINTRNEF V1, V2 // 22749d72 - VFRINTRNED V1, V2 // 22789d72 - VFRINTRZF V1, V2 // 22649d72 - VFRINTRZD V1, V2 // 22689d72 - VFRINTRPF V1, V2 // 22549d72 - VFRINTRPD V1, V2 // 22589d72 - VFRINTRMF V1, V2 // 22449d72 - VFRINTRMD V1, V2 // 22489d72 - VFRINTF V1, V2 // 22349d72 - VFRINTD V1, V2 // 22389d72 - XVFRINTRNEF X1, X2 // 22749d76 - XVFRINTRNED X1, X2 // 22789d76 - XVFRINTRZF X1, X2 // 22649d76 - XVFRINTRZD X1, X2 // 22689d76 - XVFRINTRPF X1, X2 // 22549d76 - XVFRINTRPD X1, X2 // 22589d76 - XVFRINTRMF X1, X2 // 22449d76 - XVFRINTRMD X1, X2 // 22489d76 - XVFRINTF X1, X2 // 22349d76 - XVFRINTD X1, X2 // 22389d76 - - // [X]VF{ADD/SUB/MUL/DIV}.{S/D} instructions - VADDF V1, V2, V3 // 43843071 - VADDD V1, V2, V3 // 43043171 - VSUBF V1, V2, V3 // 43843271 - VSUBD V1, V2, V3 // 43043371 - VMULF V1, V2, V3 // 43843871 - VMULD V1, V2, V3 // 43043971 - VDIVF V1, V2, V3 // 43843a71 - VDIVD V1, V2, V3 // 43043b71 - XVADDF X1, X2, X3 // 43843075 - XVADDD X1, X2, X3 // 43043175 - XVSUBF X1, X2, X3 // 43843275 - XVSUBD X1, X2, X3 // 43043375 - XVMULF X1, X2, X3 // 43843875 - XVMULD X1, X2, X3 // 43043975 - XVDIVF X1, X2, X3 // 43843a75 - XVDIVD X1, X2, X3 // 43043b75 - - // [X]VFCLASS.{S/D} instructions - VFCLASSF V1, V2 // 22d49c72 - VFCLASSD V1, V2 // 22d89c72 - XVFCLASSF X1, X2 // 22d49c76 - XVFCLASSD X1, X2 // 22d89c76 - - // PRELD{,X} instructions - PRELD (R4), $0 // 8000c02a - PRELD -1(R4), $8 // 88fcff2a - PRELD 8(R4), $31 // 9f20c02a diff --git a/src/cmd/asm/internal/asm/testdata/loong64enc5.s b/src/cmd/asm/internal/asm/testdata/loong64enc5.s index b7ecd6b63b33d8..423e5c3b01c02e 100644 --- a/src/cmd/asm/internal/asm/testdata/loong64enc5.s +++ b/src/cmd/asm/internal/asm/testdata/loong64enc5.s @@ -15,8 +15,3 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0 AND $0xfedcba9876543210, R4 // AND $-81985529216486896, R4 // 7ea8ec14de4388031e539717deb73f0384f81400 AND $0xfedcba9876543210, R5, R4 // AND $-81985529216486896, R5, R4 // 7ea8ec14de4388031e539717deb73f03a4f81400 - PRELDX 0(R7), $0x80001021, $0 // PRELDX (R7), $2147487777, $0 // 1e020014de0380031e000016de130003e0782c38 - PRELDX -1(R7), $0x1021, $2 // PRELDX -1(R7), $4129, $2 // fe030014deffbf031e000016de030003e2782c38 - PRELDX 8(R7), $0x80100800, $31 // PRELDX 8(R7), $2148534272, $31 // 1ee00714de238003fe1f0016de130003ff782c38 - PRELDX 16(R7), $0x202040, $1 // PRELDX 16(R7), $2105408, $1 // 1e200014de4380033e000216de030003e1782c38 - diff --git a/src/cmd/asm/internal/asm/testdata/riscv64.s b/src/cmd/asm/internal/asm/testdata/riscv64.s index 75abcefa10227b..1bb52e997dc22c 100644 --- a/src/cmd/asm/internal/asm/testdata/riscv64.s +++ b/src/cmd/asm/internal/asm/testdata/riscv64.s @@ -438,9 +438,9 @@ start: VSETVLI X10, E32, M2, TA, MA, X12 // 5776150d VSETVLI X10, E32, M4, TA, MA, X12 // 5776250d VSETVLI X10, E32, M8, TA, MA, X12 // 5776350d - VSETVLI X10, E32, MF8, TA, MA, X12 // 5776550d + VSETVLI X10, E32, MF2, TA, MA, X12 // 5776550d VSETVLI X10, E32, MF4, TA, MA, X12 // 5776650d - VSETVLI X10, E32, MF2, TA, MA, X12 // 5776750d + VSETVLI X10, E32, MF8, TA, MA, X12 // 5776750d VSETVLI X10, E32, M1, TA, MA, X12 // 5776050d VSETVLI $15, E32, M1, TA, MA, X12 // 57f607cd VSETIVLI $0, E32, M1, TA, MA, X12 // 577600cd @@ -623,27 +623,17 @@ start: VADCVXM X11, V2, V0, V3 // d7c12540 VADCVIM $15, V2, V0, V3 // d7b12740 VMADCVVM V1, V2, V0, V3 // d7812044 - VMADCVVM V1, V2, V0, V0 // 57802044 VMADCVXM X11, V2, V0, V3 // d7c12544 - VMADCVXM X11, V2, V0, V0 // 57c02544 VMADCVIM $15, V2, V0, V3 // d7b12744 - VMADCVIM $15, V2, V0, V0 // 57b02744 VMADCVV V1, V2, V3 // d7812046 - VMADCVV V1, V2, V0 // 57802046 VMADCVX X11, V2, V3 // d7c12546 - VMADCVX X11, V2, V0 // 57c02546 VMADCVI $15, V2, V3 // d7b12746 - VMADCVI $15, V2, V0 // 57b02746 VSBCVVM V1, V2, V0, V3 // d7812048 VSBCVXM X11, V2, V0, V3 // d7c12548 VMSBCVVM V1, V2, V0, V3 // d781204c - VMSBCVVM V1, V2, V0, V0 // 5780204c VMSBCVXM X11, V2, V0, V3 // d7c1254c - VMSBCVXM X11, V2, V0, V0 // 57c0254c VMSBCVV V1, V2, V3 // d781204e - VMSBCVV V1, V2, V0 // 5780204e VMSBCVX X11, V2, V3 // d7c1254e - VMSBCVX X11, V2, V0 // 57c0254e // 31.11.5: Vector Bitwise Logical Instructions VANDVV V1, V2, V3 // d7812026 @@ -830,38 +820,38 @@ start: VWMULSUVX X10, V2, V0, V3 // d76125e8 // 31.11.13: Vector Single-Width Integer Multiply-Add Instructions - VMACCVV V2, V1, V3 // d7a120b6 - VMACCVV V2, V1, V0, V3 // d7a120b4 - VMACCVX V2, X10, V3 // d76125b6 - VMACCVX V2, X10, V0, V3 // d76125b4 - VNMSACVV V2, V1, V3 // d7a120be - VNMSACVV V2, V1, V0, V3 // d7a120bc - VNMSACVX V2, X10, V3 // d76125be - VNMSACVX V2, X10, V0, V3 // d76125bc - VMADDVV V2, V1, V3 // d7a120a6 - VMADDVV V2, V1, V0, V3 // d7a120a4 - VMADDVX V2, X10, V3 // d76125a6 - VMADDVX V2, X10, V0, V3 // d76125a4 - VNMSUBVV V2, V1, V3 // d7a120ae - VNMSUBVV V2, V1, V0, V3 // d7a120ac - VNMSUBVX V2, X10, V3 // d76125ae - VNMSUBVX V2, X10, V0, V3 // d76125ac + VMACCVV V1, V2, V3 // d7a120b6 + VMACCVV V1, V2, V0, V3 // d7a120b4 + VMACCVX X10, V2, V3 // d76125b6 + VMACCVX X10, V2, V0, V3 // d76125b4 + VNMSACVV V1, V2, V3 // d7a120be + VNMSACVV V1, V2, V0, V3 // d7a120bc + VNMSACVX X10, V2, V3 // d76125be + VNMSACVX X10, V2, V0, V3 // d76125bc + VMADDVV V1, V2, V3 // d7a120a6 + VMADDVV V1, V2, V0, V3 // d7a120a4 + VMADDVX X10, V2, V3 // d76125a6 + VMADDVX X10, V2, V0, V3 // d76125a4 + VNMSUBVV V1, V2, V3 // d7a120ae + VNMSUBVV V1, V2, V0, V3 // d7a120ac + VNMSUBVX X10, V2, V3 // d76125ae + VNMSUBVX X10, V2, V0, V3 // d76125ac // 31.11.14: Vector Widening Integer Multiply-Add Instructions - VWMACCUVV V2, V1, V3 // d7a120f2 - VWMACCUVV V2, V1, V0, V3 // d7a120f0 - VWMACCUVX V2, X10, V3 // d76125f2 - VWMACCUVX V2, X10, V0, V3 // d76125f0 - VWMACCVV V2, V1, V3 // d7a120f6 - VWMACCVV V2, V1, V0, V3 // d7a120f4 - VWMACCVX V2, X10, V3 // d76125f6 - VWMACCVX V2, X10, V0, V3 // d76125f4 - VWMACCSUVV V2, V1, V3 // d7a120fe - VWMACCSUVV V2, V1, V0, V3 // d7a120fc - VWMACCSUVX V2, X10, V3 // d76125fe - VWMACCSUVX V2, X10, V0, V3 // d76125fc - VWMACCUSVX V2, X10, V3 // d76125fa - VWMACCUSVX V2, X10, V0, V3 // d76125f8 + VWMACCUVV V1, V2, V3 // d7a120f2 + VWMACCUVV V1, V2, V0, V3 // d7a120f0 + VWMACCUVX X10, V2, V3 // d76125f2 + VWMACCUVX X10, V2, V0, V3 // d76125f0 + VWMACCVV V1, V2, V3 // d7a120f6 + VWMACCVV V1, V2, V0, V3 // d7a120f4 + VWMACCVX X10, V2, V3 // d76125f6 + VWMACCVX X10, V2, V0, V3 // d76125f4 + VWMACCSUVV V1, V2, V3 // d7a120fe + VWMACCSUVV V1, V2, V0, V3 // d7a120fc + VWMACCSUVX X10, V2, V3 // d76125fe + VWMACCSUVX X10, V2, V0, V3 // d76125fc + VWMACCUSVX X10, V2, V3 // d76125fa + VWMACCUSVX X10, V2, V0, V3 // d76125f8 // 31.11.15: Vector Integer Merge Instructions VMERGEVVM V1, V2, V0, V3 // d781205c @@ -947,343 +937,6 @@ start: VNCLIPWI $16, V2, V3 // d73128be VNCLIPWI $16, V2, V0, V3 // d73128bc - // 31.13.2: Vector Single-Width Floating-Point Add/Subtract Instructions - VFADDVV V1, V2, V3 // d7912002 - VFADDVV V1, V2, V0, V3 // d7912000 - VFADDVF F10, V2, V3 // d7512502 - VFADDVF F10, V2, V0, V3 // d7512500 - VFSUBVV V1, V2, V3 // d791200a - VFSUBVV V1, V2, V0, V3 // d7912008 - VFSUBVF F10, V2, V3 // d751250a - VFSUBVF F10, V2, V0, V3 // d7512508 - VFRSUBVF F10, V2, V3 // d751259e - VFRSUBVF F10, V2, V0, V3 // d751259c - - // 31.13.3: Vector Widening Floating-Point Add/Subtract Instructions - VFWADDVV V1, V2, V3 // d79120c2 - VFWADDVV V1, V2, V0, V3 // d79120c0 - VFWADDVF F10, V2, V3 // d75125c2 - VFWADDVF F10, V2, V0, V3 // d75125c0 - VFWSUBVV V1, V2, V3 // d79120ca - VFWSUBVV V1, V2, V0, V3 // d79120c8 - VFWSUBVF F10, V2, V3 // d75125ca - VFWSUBVF F10, V2, V0, V3 // d75125c8 - VFWADDWV V1, V2, V3 // d79120d2 - VFWADDWV V1, V2, V0, V3 // d79120d0 - VFWADDWF F10, V2, V3 // d75125d2 - VFWADDWF F10, V2, V0, V3 // d75125d0 - VFWSUBWV V1, V2, V3 // d79120da - VFWSUBWV V1, V2, V0, V3 // d79120d8 - VFWSUBWF F10, V2, V3 // d75125da - VFWSUBWF F10, V2, V0, V3 // d75125d8 - - // 31.13.4: Vector Single-Width Floating-Point Multiply/Divide Instructions - VFMULVV V1, V2, V3 // d7912092 - VFMULVV V1, V2, V0, V3 // d7912090 - VFMULVF F10, V2, V3 // d7512592 - VFMULVF F10, V2, V0, V3 // d7512590 - VFDIVVV V1, V2, V3 // d7912082 - VFDIVVV V1, V2, V0, V3 // d7912080 - VFDIVVF F10, V2, V3 // d7512582 - VFDIVVF F10, V2, V0, V3 // d7512580 - VFRDIVVF F10, V2, V3 // d7512586 - VFRDIVVF F10, V2, V0, V3 // d7512584 - - // 31.13.5: Vector Widening Floating-Point Multiply - VFWMULVV V1, V2, V3 // d79120e2 - VFWMULVV V1, V2, V0, V3 // d79120e0 - VFWMULVF F10, V2, V3 // d75125e2 - VFWMULVF F10, V2, V0, V3 // d75125e0 - - // 31.13.6: Vector Single-Width Floating-Point Fused Multiply-Add Instructions - VFMACCVV V2, V1, V3 // d79120b2 - VFMACCVV V2, V1, V0, V3 // d79120b0 - VFMACCVF V2, F10, V3 // d75125b2 - VFMACCVF V2, F10, V0, V3 // d75125b0 - VFNMACCVV V2, V1, V3 // d79120b6 - VFNMACCVV V2, V1, V0, V3 // d79120b4 - VFNMACCVF V2, F10, V3 // d75125b6 - VFNMACCVF V2, F10, V0, V3 // d75125b4 - VFMSACVV V2, V1, V3 // d79120ba - VFMSACVV V2, V1, V0, V3 // d79120b8 - VFMSACVF V2, F10, V3 // d75125ba - VFMSACVF V2, F10, V0, V3 // d75125b8 - VFNMSACVV V2, V1, V3 // d79120be - VFNMSACVV V2, V1, V0, V3 // d79120bc - VFNMSACVF V2, F10, V3 // d75125be - VFNMSACVF V2, F10, V0, V3 // d75125bc - VFMADDVV V2, V1, V3 // d79120a2 - VFMADDVV V2, V1, V0, V3 // d79120a0 - VFMADDVF V2, F10, V3 // d75125a2 - VFMADDVF V2, F10, V0, V3 // d75125a0 - VFNMADDVV V2, V1, V3 // d79120a6 - VFNMADDVV V2, V1, V0, V3 // d79120a4 - VFNMADDVF V2, F10, V3 // d75125a6 - VFNMADDVF V2, F10, V0, V3 // d75125a4 - VFMSUBVV V2, V1, V3 // d79120aa - VFMSUBVV V2, V1, V0, V3 // d79120a8 - VFMSUBVF V2, F10, V3 // d75125aa - VFMSUBVF V2, F10, V0, V3 // d75125a8 - VFNMSUBVV V2, V1, V3 // d79120ae - VFNMSUBVV V2, V1, V0, V3 // d79120ac - VFNMSUBVF V2, F10, V3 // d75125ae - VFNMSUBVF V2, F10, V0, V3 // d75125ac - - // 31.13.7: Vector Widening Floating-Point Fused Multiply-Add Instructions - VFWMACCVV V2, V1, V3 // d79120f2 - VFWMACCVV V2, V1, V0, V3 // d79120f0 - VFWMACCVF V2, F10, V3 // d75125f2 - VFWMACCVF V2, F10, V0, V3 // d75125f0 - VFWNMACCVV V2, V1, V3 // d79120f6 - VFWNMACCVV V2, V1, V0, V3 // d79120f4 - VFWNMACCVF V2, F10, V3 // d75125f6 - VFWNMACCVF V2, F10, V0, V3 // d75125f4 - VFWMSACVV V2, V1, V3 // d79120fa - VFWMSACVV V2, V1, V0, V3 // d79120f8 - VFWMSACVF V2, F10, V3 // d75125fa - VFWMSACVF V2, F10, V0, V3 // d75125f8 - VFWNMSACVV V2, V1, V3 // d79120fe - VFWNMSACVV V2, V1, V0, V3 // d79120fc - VFWNMSACVF V2, F10, V3 // d75125fe - VFWNMSACVF V2, F10, V0, V3 // d75125fc - - // 31.13.8: Vector Floating-Point Square-Root Instruction - VFSQRTV V2, V3 // d711204e - VFSQRTV V2, V0, V3 // d711204c - - // 31.13.9: Vector Floating-Point Reciprocal Square-Root Estimate Instruction - VFRSQRT7V V2, V3 // d711224e - VFRSQRT7V V2, V0, V3 // d711224c - - // 31.13.10: Vector Floating-Point Reciprocal Estimate Instruction - VFREC7V V2, V3 // d791224e - VFREC7V V2, V0, V3 // d791224c - - // 31.13.11: Vector Floating-Point MIN/MAX Instructions - VFMINVV V1, V2, V3 // d7912012 - VFMINVV V1, V2, V0, V3 // d7912010 - VFMINVF F10, V2, V3 // d7512512 - VFMINVF F10, V2, V0, V3 // d7512510 - VFMAXVV V1, V2, V3 // d791201a - VFMAXVV V1, V2, V0, V3 // d7912018 - VFMAXVF F10, V2, V3 // d751251a - VFMAXVF F10, V2, V0, V3 // d7512518 - - // 31.13.12: Vector Floating-Point Sign-Injection Instructions - VFSGNJVV V1, V2, V3 // d7912022 - VFSGNJVV V1, V2, V0, V3 // d7912020 - VFSGNJVF F10, V2, V3 // d7512522 - VFSGNJVF F10, V2, V0, V3 // d7512520 - VFSGNJNVV V1, V2, V3 // d7912026 - VFSGNJNVV V1, V2, V0, V3 // d7912024 - VFSGNJNVF F10, V2, V3 // d7512526 - VFSGNJNVF F10, V2, V0, V3 // d7512524 - VFSGNJXVV V1, V2, V3 // d791202a - VFSGNJXVV V1, V2, V0, V3 // d7912028 - VFSGNJXVF F10, V2, V3 // d751252a - VFSGNJXVF F10, V2, V0, V3 // d7512528 - VFNEGV V2, V3 // d7112126 - VFNEGV V2, V0, V3 // d7112124 - VFABSV V2, V3 // d711212a - VFABSV V2, V0, V3 // d7112128 - - // 31.13.13: Vector Floating-Point Compare Instructions - VMFEQVV V1, V2, V3 // d7912062 - VMFEQVV V1, V2, V0, V3 // d7912060 - VMFEQVF F10, V2, V3 // d7512562 - VMFEQVF F10, V2, V0, V3 // d7512560 - VMFNEVV V1, V2, V3 // d7912072 - VMFNEVV V1, V2, V0, V3 // d7912070 - VMFNEVF F10, V2, V3 // d7512572 - VMFNEVF F10, V2, V0, V3 // d7512570 - VMFLTVV V1, V2, V3 // d791206e - VMFLTVV V1, V2, V0, V3 // d791206c - VMFLTVF F10, V2, V3 // d751256e - VMFLTVF F10, V2, V0, V3 // d751256c - VMFLEVV V1, V2, V3 // d7912066 - VMFLEVV V1, V2, V0, V3 // d7912064 - VMFLEVF F10, V2, V3 // d7512566 - VMFLEVF F10, V2, V0, V3 // d7512564 - VMFGTVF F10, V2, V3 // d7512576 - VMFGTVF F10, V2, V0, V3 // d7512574 - VMFGEVF F10, V2, V3 // d751257e - VMFGEVF F10, V2, V0, V3 // d751257c - VMFGTVV V1, V2, V3 // d711116e - VMFGTVV V1, V2, V0, V3 // d711116c - VMFGEVV V1, V2, V3 // d7111166 - VMFGEVV V1, V2, V0, V3 // d7111164 - - // 31.13.14: Vector Floating-Point Classify Instruction - VFCLASSV V2, V3 // d711284e - VFCLASSV V2, V0, V3 // d711284c - - // 31.13.15: Vector Floating-Point Merge Instruction - VFMERGEVFM F10, V2, V0, V3 // d751255c - - // 31.13.16: Vector Floating-Point Move Instruction - VFMVVF F10, V3 // d751055e - - // 31.13.17: Single-Width Floating-Point/Integer Type-Convert Instructions - VFCVTXUFV V2, V3 // d711204a - VFCVTXUFV V2, V0, V3 // d7112048 - VFCVTXFV V2, V3 // d791204a - VFCVTXFV V2, V0, V3 // d7912048 - VFCVTRTZXUFV V2, V3 // d711234a - VFCVTRTZXUFV V2, V0, V3 // d7112348 - VFCVTRTZXFV V2, V3 // d791234a - VFCVTRTZXFV V2, V0, V3 // d7912348 - VFCVTFXUV V2, V3 // d711214a - VFCVTFXUV V2, V0, V3 // d7112148 - VFCVTFXV V2, V3 // d791214a - VFCVTFXV V2, V0, V3 // d7912148 - - // 31.13.18: Widening Floating-Point/Integer Type-Convert Instructions - VFWCVTXUFV V2, V3 // d711244a - VFWCVTXUFV V2, V0, V3 // d7112448 - VFWCVTXFV V2, V3 // d791244a - VFWCVTXFV V2, V0, V3 // d7912448 - VFWCVTRTZXUFV V2, V3 // d711274a - VFWCVTRTZXUFV V2, V0, V3 // d7112748 - VFWCVTRTZXFV V2, V3 // d791274a - VFWCVTRTZXFV V2, V0, V3 // d7912748 - VFWCVTFXUV V2, V3 // d711254a - VFWCVTFXUV V2, V0, V3 // d7112548 - VFWCVTFXV V2, V3 // d791254a - VFWCVTFXV V2, V0, V3 // d7912548 - VFWCVTFFV V2, V3 // d711264a - VFWCVTFFV V2, V0, V3 // d7112648 - - // 31.13.19: Narrowing Floating-Point/Integer Type-Convert Instructions - VFNCVTXUFW V2, V3 // d711284a - VFNCVTXUFW V2, V0, V3 // d7112848 - VFNCVTXFW V2, V3 // d791284a - VFNCVTXFW V2, V0, V3 // d7912848 - VFNCVTRTZXUFW V2, V3 // d7112b4a - VFNCVTRTZXUFW V2, V0, V3 // d7112b48 - VFNCVTRTZXFW V2, V3 // d7912b4a - VFNCVTRTZXFW V2, V0, V3 // d7912b48 - VFNCVTFXUW V2, V3 // d711294a - VFNCVTFXUW V2, V0, V3 // d7112948 - VFNCVTFXW V2, V3 // d791294a - VFNCVTFXW V2, V0, V3 // d7912948 - VFNCVTFFW V2, V3 // d7112a4a - VFNCVTFFW V2, V0, V3 // d7112a48 - VFNCVTRODFFW V2, V3 // d7912a4a - VFNCVTRODFFW V2, V0, V3 // d7912a48 - - // 31.14.1: Vector Single-Width Integer Reduction Instructions - VREDSUMVS V1, V2, V3 // d7a12002 - VREDSUMVS V1, V2, V0, V3 // d7a12000 - VREDMAXUVS V1, V2, V3 // d7a1201a - VREDMAXUVS V1, V2, V0, V3 // d7a12018 - VREDMAXVS V1, V2, V3 // d7a1201e - VREDMAXVS V1, V2, V0, V3 // d7a1201c - VREDMINUVS V1, V2, V3 // d7a12012 - VREDMINUVS V1, V2, V0, V3 // d7a12010 - VREDMINVS V1, V2, V3 // d7a12016 - VREDMINVS V1, V2, V0, V3 // d7a12014 - VREDANDVS V1, V2, V3 // d7a12006 - VREDANDVS V1, V2, V0, V3 // d7a12004 - VREDORVS V1, V2, V3 // d7a1200a - VREDORVS V1, V2, V0, V3 // d7a12008 - VREDXORVS V1, V2, V3 // d7a1200e - VREDXORVS V1, V2, V0, V3 // d7a1200c - - // 31.14.2: Vector Widening Integer Reduction Instructions - VWREDSUMUVS V1, V2, V3 // d78120c2 - VWREDSUMUVS V1, V2, V0, V3 // d78120c0 - VWREDSUMVS V1, V2, V3 // d78120c6 - VWREDSUMVS V1, V2, V0, V3 // d78120c4 - - // 31.14.3: Vector Single-Width Floating-Point Reduction Instructions - VFREDOSUMVS V1, V2, V3 // d791200e - VFREDOSUMVS V1, V2, V0, V3 // d791200c - VFREDUSUMVS V1, V2, V3 // d7912006 - VFREDUSUMVS V1, V2, V0, V3 // d7912004 - VFREDMAXVS V1, V2, V3 // d791201e - VFREDMAXVS V1, V2, V0, V3 // d791201c - VFREDMINVS V1, V2, V3 // d7912016 - VFREDMINVS V1, V2, V0, V3 // d7912014 - - // 31.14.4: Vector Widening Floating-Point Reduction Instructions - VFWREDOSUMVS V1, V2, V3 // d79120ce - VFWREDOSUMVS V1, V2, V0, V3 // d79120cc - VFWREDUSUMVS V1, V2, V3 // d79120c6 - VFWREDUSUMVS V1, V2, V0, V3 // d79120c4 - - // 31.15: Vector Mask Instructions - VMANDMM V1, V2, V3 // d7a12066 - VMNANDMM V1, V2, V3 // d7a12076 - VMANDNMM V1, V2, V3 // d7a12062 - VMXORMM V1, V2, V3 // d7a1206e - VMORMM V1, V2, V3 // d7a1206a - VMNORMM V1, V2, V3 // d7a1207a - VMORNMM V1, V2, V3 // d7a12072 - VMXNORMM V1, V2, V3 // d7a1207e - VMMVM V2, V3 // d7212166 - VMCLRM V3 // d7a1316e - VMSETM V3 // d7a1317e - VMNOTM V2, V3 // d7212176 - VCPOPM V2, X10 // 57252842 - VCPOPM V2, V0, X10 // 57252840 - VFIRSTM V2, X10 // 57a52842 - VFIRSTM V2, V0, X10 // 57a52840 - VMSBFM V2, V3 // d7a12052 - VMSBFM V2, V0, V3 // d7a12050 - VMSIFM V2, V3 // d7a12152 - VMSIFM V2, V0, V3 // d7a12150 - VMSOFM V2, V3 // d7212152 - VMSOFM V2, V0, V3 // d7212150 - VIOTAM V2, V3 // d7212852 - VIOTAM V2, V0, V3 // d7212850 - VIDV V3 // d7a10852 - VIDV V0, V3 // d7a10850 - - // 31.16.1: Integer Scalar Move Instructions - VMVXS V2, X10 // 57252042 - VMVSX X10, V2 // 57610542 - - // 31.16.2: Floating-Point Scalar Move Instructions - VFMVFS V2, F10 // 57152042 - VFMVSF F10, V2 // 57510542 - - // 31.16.3: Vector Slide Instructions - VSLIDEUPVX X10, V2, V3 // d741253a - VSLIDEUPVX X10, V2, V0, V3 // d7412538 - VSLIDEUPVI $16, V2, V3 // d731283a - VSLIDEUPVI $16, V2, V0, V3 // d7312838 - VSLIDEDOWNVX X10, V2, V3 // d741253e - VSLIDEDOWNVX X10, V2, V0, V3 // d741253c - VSLIDEDOWNVI $16, V2, V3 // d731283e - VSLIDEDOWNVI $16, V2, V0, V3 // d731283c - VSLIDE1UPVX X10, V2, V3 // d761253a - VSLIDE1UPVX X10, V2, V0, V3 // d7612538 - VFSLIDE1UPVF F10, V2, V3 // d751253a - VFSLIDE1UPVF F10, V2, V0, V3 // d7512538 - VSLIDE1DOWNVX X10, V2, V3 // d761253e - VSLIDE1DOWNVX X10, V2, V0, V3 // d761253c - VFSLIDE1DOWNVF F10, V2, V3 // d751253e - VFSLIDE1DOWNVF F10, V2, V0, V3 // d751253c - - // 31.16.4: Vector Register Gather Instructions - VRGATHERVV V1, V2, V3 // d7812032 - VRGATHERVV V1, V2, V0, V3 // d7812030 - VRGATHEREI16VV V1, V2, V3 // d781203a - VRGATHEREI16VV V1, V2, V0, V3 // d7812038 - VRGATHERVX X10, V2, V3 // d7412532 - VRGATHERVX X10, V2, V0, V3 // d7412530 - VRGATHERVI $16, V2, V3 // d7312832 - VRGATHERVI $16, V2, V0, V3 // d7312830 - - // 31.16.5: Vector Compress Instruction - VCOMPRESSVM V1, V2, V3 // d7a1205e - - // 31.16.6: Whole Vector Register Move - VMV1RV V2, V1 // d730209e - VMV2RV V12, V10 // 57b5c09e - VMV4RV V8, V4 // 57b2819e - VMV8RV V8, V0 // 57b0839e - // // Privileged ISA // diff --git a/src/cmd/asm/internal/asm/testdata/riscv64error.s b/src/cmd/asm/internal/asm/testdata/riscv64error.s index 4e6afa0ac2a619..6a7c9b944454f8 100644 --- a/src/cmd/asm/internal/asm/testdata/riscv64error.s +++ b/src/cmd/asm/internal/asm/testdata/riscv64error.s @@ -50,340 +50,208 @@ TEXT errors(SB),$0 // // "V" Standard Extension for Vector Operations, Version 1.0 // - VSETIVLI X10, E32, M2, TA, MA, X12 // ERROR "expected immediate value" - VLE8V (X10), V1, V3 // ERROR "invalid vector mask register" - VSE8V V3, V1, (X10) // ERROR "invalid vector mask register" - VLSE8V (X10), X10, V1, V3 // ERROR "invalid vector mask register" - VSSE8V V3, X11, V1, (X10) // ERROR "invalid vector mask register" - VLUXEI8V (X10), V2, V1, V3 // ERROR "invalid vector mask register" - VSUXEI8V V3, V2, V1, (X10) // ERROR "invalid vector mask register" - VLOXEI8V (X10), V2, V1, V3 // ERROR "invalid vector mask register" - VSOXEI8V V3, V2, V1, (X10) // ERROR "invalid vector mask register" - VL1RV (X10), V0, V3 // ERROR "too many operands for instruction" - VS1RV V3, V0, (X11) // ERROR "too many operands for instruction" - VADDVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VADDVX X10, V2, V1, V3 // ERROR "invalid vector mask register" - VADDVI $15, V4, V1, V2 // ERROR "invalid vector mask register" - VSUBVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VSUBVX X10, V2, V1, V3 // ERROR "invalid vector mask register" - VRSUBVX X10, V2, V1, V3 // ERROR "invalid vector mask register" - VRSUBVI $15, V4, V1, V2 // ERROR "invalid vector mask register" - VNEGV V2, V3, V4 // ERROR "invalid vector mask register" - VWADDUVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VWADDUVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VWSUBUVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VWSUBUVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VWADDVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VWADDVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VWSUBVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VWSUBVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VWADDUWV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VWADDUWX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VWSUBUWV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VWSUBUWX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VWADDWV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VWADDWX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VWSUBWV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VWSUBWX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VWCVTXXV V2, V1, V3 // ERROR "invalid vector mask register" - VWCVTUXXV V2, V1, V3 // ERROR "invalid vector mask register" - VZEXTVF2 V2, V3, V4 // ERROR "invalid vector mask register" - VSEXTVF2 V2, V3, V4 // ERROR "invalid vector mask register" - VZEXTVF4 V2, V3, V4 // ERROR "invalid vector mask register" - VSEXTVF4 V2, V3, V4 // ERROR "invalid vector mask register" - VZEXTVF8 V2, V3, V4 // ERROR "invalid vector mask register" - VSEXTVF8 V2, V3, V4 // ERROR "invalid vector mask register" - VADCVVM V1, V2, V4, V3 // ERROR "invalid vector mask register" - VADCVVM V1, V2, V3 // ERROR "invalid vector mask register" - VADCVVM V1, V2, V0, V0 // ERROR "invalid destination register V0" - VADCVXM X10, V2, V4, V3 // ERROR "invalid vector mask register" - VADCVXM X10, V2, V3 // ERROR "invalid vector mask register" - VADCVXM X10, V2, V0, V0 // ERROR "invalid destination register V0" - VADCVIM $15, V2, V1, V3 // ERROR "invalid vector mask register" - VADCVIM $15, V2, V3 // ERROR "invalid vector mask register" - VADCVIM $15, V2, V0, V0 // ERROR "invalid destination register V0" - VMADCVVM V1, V2, V4, V3 // ERROR "invalid vector mask register" - VMADCVVM V1, V2, V3 // ERROR "invalid vector mask register" - VMADCVXM X10, V2, V4, V3 // ERROR "invalid vector mask register" - VMADCVXM X10, V2, V3 // ERROR "invalid vector mask register" - VMADCVIM $15, V2, V1, V3 // ERROR "invalid vector mask register" - VMADCVIM $15, V2, V3 // ERROR "invalid vector mask register" - VSBCVVM V1, V2, V4, V3 // ERROR "invalid vector mask register" - VSBCVVM V1, V2, V3 // ERROR "invalid vector mask register" - VSBCVVM V1, V2, V0, V0 // ERROR "invalid destination register V0" - VSBCVXM X10, V2, V4, V3 // ERROR "invalid vector mask register" - VSBCVXM X10, V2, V3 // ERROR "invalid vector mask register" - VSBCVXM X10, V2, V0, V0 // ERROR "invalid destination register V0" - VMSBCVVM V1, V2, V4, V3 // ERROR "invalid vector mask register" - VMSBCVVM V1, V2, V3 // ERROR "invalid vector mask register" - VMSBCVXM X10, V2, V4, V3 // ERROR "invalid vector mask register" - VMSBCVXM X10, V2, V3 // ERROR "invalid vector mask register" - VANDVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VANDVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VANDVI $15, V2, V4, V3 // ERROR "invalid vector mask register" - VORVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VORVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VORVI $15, V2, V4, V3 // ERROR "invalid vector mask register" - VXORVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VXORVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VXORVI $15, V2, V4, V3 // ERROR "invalid vector mask register" - VNOTV V1, V2, V3 // ERROR "invalid vector mask register" - VSLLVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VSLLVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VSLLVI $15, V2, V4, V3 // ERROR "invalid vector mask register" - VSRLVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VSRLVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VSRLVI $15, V2, V4, V3 // ERROR "invalid vector mask register" - VSRAVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VSRAVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VSRAVI $15, V2, V4, V3 // ERROR "invalid vector mask register" - VNSRLWV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VNSRLWX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VNSRLWI $31, V2, V4, V3 // ERROR "invalid vector mask register" - VNSRAWV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VNSRAWX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VNSRAWI $31, V2, V4, V3 // ERROR "invalid vector mask register" - VNCVTXXW V2, V4, V3 // ERROR "invalid vector mask register" - VMSEQVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VMSEQVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VMSEQVI $15, V2, V4, V3 // ERROR "invalid vector mask register" - VMSNEVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VMSNEVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VMSNEVI $15, V2, V4, V3 // ERROR "invalid vector mask register" - VMSLTUVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VMSLTUVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VMSLTVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VMSLTVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VMSLEUVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VMSLEUVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VMSLEUVI $15, V2, V4, V3 // ERROR "invalid vector mask register" - VMSLEVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VMSLEVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VMSLEVI $15, V2, V4, V3 // ERROR "invalid vector mask register" - VMSGTUVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VMSGTUVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VMSGTUVI $15, V2, V4, V3 // ERROR "invalid vector mask register" - VMSGTVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VMSGTVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VMSGTVI $15, V2, V4, V3 // ERROR "invalid vector mask register" - VMSGEVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VMSGEUVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VMSLTVI $15, V2, V4, V3 // ERROR "invalid vector mask register" - VMSLTUVI $15, V2, V4, V3 // ERROR "invalid vector mask register" - VMSGEVI $15, V2, V4, V3 // ERROR "invalid vector mask register" - VMSGEUVI $15, V2, V4, V3 // ERROR "invalid vector mask register" - VMINUVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VMINUVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VMINVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VMINVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VMAXUVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VMAXUVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VMAXVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VMAXVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VMULVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VMULVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VMULHVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VMULHVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VMULHUVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VMULHUVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VMULHSUVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VMULHSUVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VDIVUVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VDIVUVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VDIVVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VDIVVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VREMUVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VREMUVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VREMVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VREMVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VWMULVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VWMULVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VWMULUVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VWMULUVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VWMULSUVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VWMULSUVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VMACCVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VMACCVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VNMSACVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VNMSACVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VMADDVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VMADDVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VNMSUBVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VNMSUBVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VWMACCUVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VWMACCUVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VWMACCVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VWMACCVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VWMACCSUVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VWMACCSUVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VWMACCUSVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VMERGEVVM V1, V2, V3 // ERROR "invalid vector mask register" - VMERGEVVM V1, V2, V4, V3 // ERROR "invalid vector mask register" - VMERGEVXM X10, V2, V3 // ERROR "invalid vector mask register" - VMERGEVXM X10, V2, V4, V3 // ERROR "invalid vector mask register" - VMERGEVIM $15, V2, V3 // ERROR "invalid vector mask register" - VMERGEVIM $15, V2, V4, V3 // ERROR "invalid vector mask register" - VMVVV V1, V2, V3 // ERROR "too many operands for instruction" - VMVVX X10, V2, V3 // ERROR "too many operands for instruction" - VMVVI $15, V2, V3 // ERROR "too many operands for instruction" - VSADDUVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VSADDUVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VSADDUVI $15, V2, V4, V3 // ERROR "invalid vector mask register" - VSADDVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VSADDVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VSADDVI $15, V2, V4, V3 // ERROR "invalid vector mask register" - VSSUBUVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VSSUBUVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VSSUBVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VSSUBVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VAADDUVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VAADDUVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VAADDVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VAADDVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VASUBUVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VASUBUVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VASUBVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VASUBVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VSMULVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VSMULVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VSSRLVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VSSRLVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VSSRLVI $15, V2, V4, V3 // ERROR "invalid vector mask register" - VSSRAVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VSSRAVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VSSRAVI $15, V2, V4, V3 // ERROR "invalid vector mask register" - VNCLIPUWV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VNCLIPUWX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VNCLIPUWI $16, V2, V4, V3 // ERROR "invalid vector mask register" - VNCLIPWV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VNCLIPWX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VNCLIPWI $16, V2, V4, V3 // ERROR "invalid vector mask register" - VFADDVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VFADDVF F10, V2, V4, V3 // ERROR "invalid vector mask register" - VFSUBVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VFSUBVF F10, V2, V4, V3 // ERROR "invalid vector mask register" - VFRSUBVF F10, V2, V4, V3 // ERROR "invalid vector mask register" - VFWADDVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VFWADDVF F10, V2, V4, V3 // ERROR "invalid vector mask register" - VFWSUBVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VFWSUBVF F10, V2, V4, V3 // ERROR "invalid vector mask register" - VFWADDWV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VFWADDWF F10, V2, V4, V3 // ERROR "invalid vector mask register" - VFWSUBWV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VFWSUBWF F10, V2, V4, V3 // ERROR "invalid vector mask register" - VFMULVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VFMULVF F10, V2, V4, V3 // ERROR "invalid vector mask register" - VFDIVVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VFDIVVF F10, V2, V4, V3 // ERROR "invalid vector mask register" - VFRDIVVF F10, V2, V4, V3 // ERROR "invalid vector mask register" - VFWMULVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VFWMULVF F10, V2, V4, V3 // ERROR "invalid vector mask register" - VFMACCVV V2, V1, V4, V3 // ERROR "invalid vector mask register" - VFMACCVF V2, F10, V4, V3 // ERROR "invalid vector mask register" - VFNMACCVV V2, V1, V4, V3 // ERROR "invalid vector mask register" - VFNMACCVF V2, F10, V4, V3 // ERROR "invalid vector mask register" - VFMSACVV V2, V1, V4, V3 // ERROR "invalid vector mask register" - VFMSACVF V2, F10, V4, V3 // ERROR "invalid vector mask register" - VFNMSACVV V2, V1, V4, V3 // ERROR "invalid vector mask register" - VFNMSACVF V2, F10, V4, V3 // ERROR "invalid vector mask register" - VFMADDVV V2, V1, V4, V3 // ERROR "invalid vector mask register" - VFMADDVF V2, F10, V4, V3 // ERROR "invalid vector mask register" - VFNMADDVV V2, V1, V4, V3 // ERROR "invalid vector mask register" - VFNMADDVF V2, F10, V4, V3 // ERROR "invalid vector mask register" - VFMSUBVV V2, V1, V4, V3 // ERROR "invalid vector mask register" - VFMSUBVF V2, F10, V4, V3 // ERROR "invalid vector mask register" - VFNMSUBVV V2, V1, V4, V3 // ERROR "invalid vector mask register" - VFNMSUBVF V2, F10, V4, V3 // ERROR "invalid vector mask register" - VFWMACCVV V2, V1, V4, V3 // ERROR "invalid vector mask register" - VFWMACCVF V2, F10, V4, V3 // ERROR "invalid vector mask register" - VFWNMACCVV V2, V1, V4, V3 // ERROR "invalid vector mask register" - VFWNMACCVF V2, F10, V4, V3 // ERROR "invalid vector mask register" - VFWMSACVV V2, V1, V4, V3 // ERROR "invalid vector mask register" - VFWMSACVF V2, F10, V4, V3 // ERROR "invalid vector mask register" - VFWNMSACVV V2, V1, V4, V3 // ERROR "invalid vector mask register" - VFWNMSACVF V2, F10, V4, V3 // ERROR "invalid vector mask register" - VFSQRTV V2, V4, V3 // ERROR "invalid vector mask register" - VFRSQRT7V V2, V4, V3 // ERROR "invalid vector mask register" - VFREC7V V2, V4, V3 // ERROR "invalid vector mask register" - VFMINVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VFMINVF F10, V2, V4, V3 // ERROR "invalid vector mask register" - VFMAXVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VFMAXVF F10, V2, V4, V3 // ERROR "invalid vector mask register" - VFSGNJVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VFSGNJVF F10, V2, V4, V3 // ERROR "invalid vector mask register" - VFSGNJNVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VFSGNJNVF F10, V2, V4, V3 // ERROR "invalid vector mask register" - VFSGNJXVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VFSGNJXVF F10, V2, V4, V3 // ERROR "invalid vector mask register" - VFNEGV V2, V4, V3 // ERROR "invalid vector mask register" - VFABSV V2, V4, V3 // ERROR "invalid vector mask register" - VMFEQVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VMFEQVF F10, V2, V4, V3 // ERROR "invalid vector mask register" - VMFNEVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VMFNEVF F10, V2, V4, V3 // ERROR "invalid vector mask register" - VMFLTVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VMFLTVF F10, V2, V4, V3 // ERROR "invalid vector mask register" - VMFLEVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VMFLEVF F10, V2, V4, V3 // ERROR "invalid vector mask register" - VMFGTVF F10, V2, V4, V3 // ERROR "invalid vector mask register" - VMFGEVF F10, V2, V4, V3 // ERROR "invalid vector mask register" - VMFGTVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VMFGEVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VFMERGEVFM X10, V2, V3 // ERROR "invalid vector mask register" - VFMERGEVFM F10, V2, V4, V3 // ERROR "invalid vector mask register" - VFCVTXUFV V2, V4, V3 // ERROR "invalid vector mask register" - VFCVTXFV V2, V4, V3 // ERROR "invalid vector mask register" - VFCVTRTZXUFV V2, V4, V3 // ERROR "invalid vector mask register" - VFCVTRTZXFV V2, V4, V3 // ERROR "invalid vector mask register" - VFCVTFXUV V2, V4, V3 // ERROR "invalid vector mask register" - VFCVTFXV V2, V4, V3 // ERROR "invalid vector mask register" - VFWCVTXUFV V2, V4, V3 // ERROR "invalid vector mask register" - VFWCVTXFV V2, V4, V3 // ERROR "invalid vector mask register" - VFWCVTRTZXUFV V2, V4, V3 // ERROR "invalid vector mask register" - VFWCVTRTZXFV V2, V4, V3 // ERROR "invalid vector mask register" - VFWCVTFXUV V2, V4, V3 // ERROR "invalid vector mask register" - VFWCVTFXV V2, V4, V3 // ERROR "invalid vector mask register" - VFWCVTFFV V2, V4, V3 // ERROR "invalid vector mask register" - VFNCVTXUFW V2, V4, V3 // ERROR "invalid vector mask register" - VFNCVTXFW V2, V4, V3 // ERROR "invalid vector mask register" - VFNCVTRTZXUFW V2, V4, V3 // ERROR "invalid vector mask register" - VFNCVTRTZXFW V2, V4, V3 // ERROR "invalid vector mask register" - VFNCVTFXUW V2, V4, V3 // ERROR "invalid vector mask register" - VFNCVTFXW V2, V4, V3 // ERROR "invalid vector mask register" - VFNCVTFFW V2, V4, V3 // ERROR "invalid vector mask register" - VFNCVTRODFFW V2, V4, V3 // ERROR "invalid vector mask register" - VREDSUMVS V1, V2, V4, V3 // ERROR "invalid vector mask register" - VREDMAXUVS V1, V2, V4, V3 // ERROR "invalid vector mask register" - VREDMAXVS V1, V2, V4, V3 // ERROR "invalid vector mask register" - VREDMINUVS V1, V2, V4, V3 // ERROR "invalid vector mask register" - VREDMINVS V1, V2, V4, V3 // ERROR "invalid vector mask register" - VREDANDVS V1, V2, V4, V3 // ERROR "invalid vector mask register" - VREDORVS V1, V2, V4, V3 // ERROR "invalid vector mask register" - VREDXORVS V1, V2, V4, V3 // ERROR "invalid vector mask register" - VWREDSUMUVS V1, V2, V4, V3 // ERROR "invalid vector mask register" - VWREDSUMVS V1, V2, V4, V3 // ERROR "invalid vector mask register" - VFREDOSUMVS V1, V2, V4, V3 // ERROR "invalid vector mask register" - VFREDUSUMVS V1, V2, V4, V3 // ERROR "invalid vector mask register" - VFREDMAXVS V1, V2, V4, V3 // ERROR "invalid vector mask register" - VFREDMINVS V1, V2, V4, V3 // ERROR "invalid vector mask register" - VFWREDOSUMVS V1, V2, V4, V3 // ERROR "invalid vector mask register" - VCPOPM V2, V4, X10 // ERROR "invalid vector mask register" - VFIRSTM V2, V4, X10 // ERROR "invalid vector mask register" - VMSBFM V2, V4, V3 // ERROR "invalid vector mask register" - VMSIFM V2, V4, V3 // ERROR "invalid vector mask register" - VMSOFM V2, V4, V3 // ERROR "invalid vector mask register" - VIOTAM V2, V4, V3 // ERROR "invalid vector mask register" - VSLIDEUPVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VSLIDEUPVI $16, V2, V4, V3 // ERROR "invalid vector mask register" - VSLIDEDOWNVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VSLIDEDOWNVI $16, V2, V4, V3 // ERROR "invalid vector mask register" - VSLIDE1UPVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VFSLIDE1UPVF F10, V2, V4, V3 // ERROR "invalid vector mask register" - VSLIDE1DOWNVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VFSLIDE1DOWNVF F10, V2, V4, V3 // ERROR "invalid vector mask register" - VRGATHERVV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VRGATHEREI16VV V1, V2, V4, V3 // ERROR "invalid vector mask register" - VRGATHERVX X10, V2, V4, V3 // ERROR "invalid vector mask register" - VRGATHERVI $16, V2, V4, V3 // ERROR "invalid vector mask register" + VSETIVLI X10, E32, M2, TA, MA, X12 // ERROR "expected immediate value" + VLE8V (X10), V1, V3 // ERROR "invalid vector mask register" + VSE8V V3, V1, (X10) // ERROR "invalid vector mask register" + VLSE8V (X10), X10, V1, V3 // ERROR "invalid vector mask register" + VSSE8V V3, X11, V1, (X10) // ERROR "invalid vector mask register" + VLUXEI8V (X10), V2, V1, V3 // ERROR "invalid vector mask register" + VSUXEI8V V3, V2, V1, (X10) // ERROR "invalid vector mask register" + VLOXEI8V (X10), V2, V1, V3 // ERROR "invalid vector mask register" + VSOXEI8V V3, V2, V1, (X10) // ERROR "invalid vector mask register" + VL1RV (X10), V0, V3 // ERROR "too many operands for instruction" + VS1RV V3, V0, (X11) // ERROR "too many operands for instruction" + VADDVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VADDVX X10, V2, V1, V3 // ERROR "invalid vector mask register" + VADDVI $15, V4, V1, V2 // ERROR "invalid vector mask register" + VSUBVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VSUBVX X10, V2, V1, V3 // ERROR "invalid vector mask register" + VRSUBVX X10, V2, V1, V3 // ERROR "invalid vector mask register" + VRSUBVI $15, V4, V1, V2 // ERROR "invalid vector mask register" + VNEGV V2, V3, V4 // ERROR "invalid vector mask register" + VWADDUVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VWADDUVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VWSUBUVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VWSUBUVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VWADDVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VWADDVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VWSUBVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VWSUBVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VWADDUWV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VWADDUWX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VWSUBUWV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VWSUBUWX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VWADDWV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VWADDWX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VWSUBWV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VWSUBWX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VWCVTXXV V2, V1, V3 // ERROR "invalid vector mask register" + VWCVTUXXV V2, V1, V3 // ERROR "invalid vector mask register" + VZEXTVF2 V2, V3, V4 // ERROR "invalid vector mask register" + VSEXTVF2 V2, V3, V4 // ERROR "invalid vector mask register" + VZEXTVF4 V2, V3, V4 // ERROR "invalid vector mask register" + VSEXTVF4 V2, V3, V4 // ERROR "invalid vector mask register" + VZEXTVF8 V2, V3, V4 // ERROR "invalid vector mask register" + VSEXTVF8 V2, V3, V4 // ERROR "invalid vector mask register" + VADCVVM V1, V2, V4, V3 // ERROR "invalid vector mask register" + VADCVVM V1, V2, V3 // ERROR "invalid vector mask register" + VADCVXM X10, V2, V4, V3 // ERROR "invalid vector mask register" + VADCVXM X10, V2, V3 // ERROR "invalid vector mask register" + VADCVIM $15, V2, V1, V3 // ERROR "invalid vector mask register" + VADCVIM $15, V2, V3 // ERROR "invalid vector mask register" + VMADCVVM V1, V2, V4, V3 // ERROR "invalid vector mask register" + VMADCVVM V1, V2, V3 // ERROR "invalid vector mask register" + VMADCVXM X10, V2, V4, V3 // ERROR "invalid vector mask register" + VMADCVXM X10, V2, V3 // ERROR "invalid vector mask register" + VMADCVIM $15, V2, V1, V3 // ERROR "invalid vector mask register" + VMADCVIM $15, V2, V3 // ERROR "invalid vector mask register" + VSBCVVM V1, V2, V4, V3 // ERROR "invalid vector mask register" + VSBCVVM V1, V2, V3 // ERROR "invalid vector mask register" + VSBCVXM X10, V2, V4, V3 // ERROR "invalid vector mask register" + VSBCVXM X10, V2, V3 // ERROR "invalid vector mask register" + VMSBCVVM V1, V2, V4, V3 // ERROR "invalid vector mask register" + VMSBCVVM V1, V2, V3 // ERROR "invalid vector mask register" + VMSBCVXM X10, V2, V4, V3 // ERROR "invalid vector mask register" + VMSBCVXM X10, V2, V3 // ERROR "invalid vector mask register" + VANDVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VANDVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VANDVI $15, V2, V4, V3 // ERROR "invalid vector mask register" + VORVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VORVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VORVI $15, V2, V4, V3 // ERROR "invalid vector mask register" + VXORVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VXORVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VXORVI $15, V2, V4, V3 // ERROR "invalid vector mask register" + VNOTV V1, V2, V3 // ERROR "invalid vector mask register" + VSLLVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VSLLVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VSLLVI $15, V2, V4, V3 // ERROR "invalid vector mask register" + VSRLVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VSRLVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VSRLVI $15, V2, V4, V3 // ERROR "invalid vector mask register" + VSRAVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VSRAVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VSRAVI $15, V2, V4, V3 // ERROR "invalid vector mask register" + VNSRLWV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VNSRLWX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VNSRLWI $31, V2, V4, V3 // ERROR "invalid vector mask register" + VNSRAWV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VNSRAWX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VNSRAWI $31, V2, V4, V3 // ERROR "invalid vector mask register" + VNCVTXXW V2, V4, V3 // ERROR "invalid vector mask register" + VMSEQVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VMSEQVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VMSEQVI $15, V2, V4, V3 // ERROR "invalid vector mask register" + VMSNEVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VMSNEVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VMSNEVI $15, V2, V4, V3 // ERROR "invalid vector mask register" + VMSLTUVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VMSLTUVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VMSLTVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VMSLTVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VMSLEUVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VMSLEUVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VMSLEUVI $15, V2, V4, V3 // ERROR "invalid vector mask register" + VMSLEVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VMSLEVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VMSLEVI $15, V2, V4, V3 // ERROR "invalid vector mask register" + VMSGTUVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VMSGTUVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VMSGTUVI $15, V2, V4, V3 // ERROR "invalid vector mask register" + VMSGTVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VMSGTVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VMSGTVI $15, V2, V4, V3 // ERROR "invalid vector mask register" + VMSGEVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VMSGEUVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VMSLTVI $15, V2, V4, V3 // ERROR "invalid vector mask register" + VMSLTUVI $15, V2, V4, V3 // ERROR "invalid vector mask register" + VMSGEVI $15, V2, V4, V3 // ERROR "invalid vector mask register" + VMSGEUVI $15, V2, V4, V3 // ERROR "invalid vector mask register" + VMINUVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VMINUVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VMINVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VMINVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VMAXUVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VMAXUVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VMAXVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VMAXVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VMULVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VMULVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VMULHVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VMULHVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VMULHUVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VMULHUVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VMULHSUVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VMULHSUVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VDIVUVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VDIVUVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VDIVVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VDIVVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VREMUVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VREMUVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VREMVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VREMVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VWMULVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VWMULVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VWMULUVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VWMULUVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VWMULSUVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VWMULSUVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VMACCVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VMACCVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VNMSACVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VNMSACVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VMADDVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VMADDVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VNMSUBVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VNMSUBVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VWMACCUVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VWMACCUVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VWMACCVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VWMACCVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VWMACCSUVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VWMACCSUVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VWMACCUSVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VMERGEVVM V1, V2, V3 // ERROR "invalid vector mask register" + VMERGEVVM V1, V2, V4, V3 // ERROR "invalid vector mask register" + VMERGEVXM X10, V2, V3 // ERROR "invalid vector mask register" + VMERGEVXM X10, V2, V4, V3 // ERROR "invalid vector mask register" + VMERGEVIM $15, V2, V3 // ERROR "invalid vector mask register" + VMERGEVIM $15, V2, V4, V3 // ERROR "invalid vector mask register" + VMVVV V1, V2, V3 // ERROR "too many operands for instruction" + VMVVX X10, V2, V3 // ERROR "too many operands for instruction" + VMVVI $15, V2, V3 // ERROR "too many operands for instruction" + VSADDUVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VSADDUVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VSADDUVI $15, V2, V4, V3 // ERROR "invalid vector mask register" + VSADDVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VSADDVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VSADDVI $15, V2, V4, V3 // ERROR "invalid vector mask register" + VSSUBUVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VSSUBUVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VSSUBVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VSSUBVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VAADDUVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VAADDUVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VAADDVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VAADDVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VASUBUVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VASUBUVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VASUBVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VASUBVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VSMULVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VSMULVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VSSRLVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VSSRLVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VSSRLVI $15, V2, V4, V3 // ERROR "invalid vector mask register" + VSSRAVV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VSSRAVX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VSSRAVI $15, V2, V4, V3 // ERROR "invalid vector mask register" + VNCLIPUWV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VNCLIPUWX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VNCLIPUWI $16, V2, V4, V3 // ERROR "invalid vector mask register" + VNCLIPWV V1, V2, V4, V3 // ERROR "invalid vector mask register" + VNCLIPWX X10, V2, V4, V3 // ERROR "invalid vector mask register" + VNCLIPWI $16, V2, V4, V3 // ERROR "invalid vector mask register" RET diff --git a/src/cmd/asm/internal/asm/testdata/riscv64validation.s b/src/cmd/asm/internal/asm/testdata/riscv64validation.s index 55bf518e68bba5..c6f71e64fb4c59 100644 --- a/src/cmd/asm/internal/asm/testdata/riscv64validation.s +++ b/src/cmd/asm/internal/asm/testdata/riscv64validation.s @@ -15,417 +15,259 @@ TEXT validation(SB),$0 // // "V" Standard Extension for Vector Operations, Version 1.0 // - VSETVLI $32, E16, M1, TU, MU, X12 // ERROR "must be in range [0, 31] (5 bits)" - VSETVLI $-1, E32, M2, TA, MA, X12 // ERROR "must be in range [0, 31] (5 bits)" - VSETVL X10, X11 // ERROR "expected integer register in rs1 position" - VLE8V (X10), X10 // ERROR "expected vector register in vd position" - VLE8V (V1), V3 // ERROR "expected integer register in rs1 position" - VSE8V X10, (X10) // ERROR "expected vector register in vs1 position" - VSE8V V3, (V1) // ERROR "expected integer register in rd position" - VLSE8V (X10), V3 // ERROR "expected integer register in rs2 position" - VLSE8V (X10), X10, X11 // ERROR "expected vector register in vd position" - VLSE8V (V1), X10, V3 // ERROR "expected integer register in rs1 position" - VLSE8V (X10), V1, V0, V3 // ERROR "expected integer register in rs2 position" - VSSE8V V3, (X10) // ERROR "expected integer register in rs2 position" - VSSE8V X10, X11, (X10) // ERROR "expected vector register in vd position" - VSSE8V V3, X11, (V1) // ERROR "expected integer register in rs1 position" - VSSE8V V3, V1, V0, (X10) // ERROR "expected integer register in rs2 position" - VLUXEI8V (X10), V2, X11 // ERROR "expected vector register in vd position" - VLUXEI8V (X10), V2, X11 // ERROR "expected vector register in vd position" - VLUXEI8V (V1), V2, V3 // ERROR "expected integer register in rs1 position" - VLUXEI8V (X10), X11, V0, V3 // ERROR "expected vector register in vs2 position" - VSUXEI8V X10, V2, (X10) // ERROR "expected vector register in vd position" - VSUXEI8V V3, V2, (V1) // ERROR "expected integer register in rs1 position" - VSUXEI8V V3, X11, V0, (X10) // ERROR "expected vector register in vs2 position" - VLOXEI8V (X10), V2, X11 // ERROR "expected vector register in vd position" - VLOXEI8V (V1), V2, V3 // ERROR "expected integer register in rs1 position" - VLOXEI8V (X10), X11, V0, V3 // ERROR "expected vector register in vs2 position" - VSOXEI8V X10, V2, (X10) // ERROR "expected vector register in vd position" - VSOXEI8V V3, V2, (V1) // ERROR "expected integer register in rs1 position" - VSOXEI8V V3, X11, V0, (X10) // ERROR "expected vector register in vs2 position" - VL1RV (X10), X10 // ERROR "expected vector register in vd position" - VL1RV (V1), V3 // ERROR "expected integer register in rs1 position" - VS1RV X11, (X11) // ERROR "expected vector register in vs1 position" - VS1RV V3, (V1) // ERROR "expected integer register in rd position" - VADDVV V1, X10, V3 // ERROR "expected vector register in vs2 position" - VADDVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VADDVI $16, V4, V2 // ERROR "signed immediate 16 must be in range [-16, 15] (5 bits)" - VADDVI $-17, V4, V2 // ERROR "signed immediate -17 must be in range [-16, 15] (5 bits)" - VSUBVV V1, X10, V3 // ERROR "expected vector register in vs2 position" - VSUBVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VRSUBVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VRSUBVI $16, V4, V2 // ERROR "signed immediate 16 must be in range [-16, 15] (5 bits)" - VRSUBVI $-17, V4, V2 // ERROR "signed immediate -17 must be in range [-16, 15] (5 bits)" - VNEGV X10, V3 // ERROR "expected vector register in vs2 position" - VNEGV V2 // ERROR "expected vector register in vd position" - VWADDUVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VWADDUVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VWSUBUVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VWSUBUVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VWADDVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VWADDVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VWSUBVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VWSUBVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VWADDUWV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VWADDUWX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VWSUBUWV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VWSUBUWX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VWADDWV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VWADDWX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VWSUBWV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VWSUBWX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VWCVTXXV X10, V3 // ERROR "expected vector register in vs2 position" - VWCVTUXXV X10, V3 // ERROR "expected vector register in vs2 position" - VZEXTVF2 V2, V0, V3, V4 // ERROR "expected no register in rs3" - VZEXTVF2 X10, V3 // ERROR "expected vector register in vs2 position" - VSEXTVF2 V2, V0, V3, V4 // ERROR "expected no register in rs3" - VSEXTVF2 X10, V3 // ERROR "expected vector register in vs2 position" - VZEXTVF4 V2, V0, V3, V4 // ERROR "expected no register in rs3" - VZEXTVF4 X10, V3 // ERROR "expected vector register in vs2 position" - VSEXTVF4 V2, V0, V3, V4 // ERROR "expected no register in rs3" - VSEXTVF4 X10, V3 // ERROR "expected vector register in vs2 position" - VZEXTVF8 V2, V0, V3, V4 // ERROR "expected no register in rs3" - VZEXTVF8 X10, V3 // ERROR "expected vector register in vs2 position" - VSEXTVF8 V2, V0, V3, V4 // ERROR "expected no register in rs3" - VSEXTVF8 X10, V3 // ERROR "expected vector register in vs2 position" - VADCVVM X10, V2, V0, V3 // ERROR "expected vector register in vs1 position" - VADCVXM V1, V2, V0, V3 // ERROR "expected integer register in rs1 position" - VADCVIM $16, V2, V0, V3 // ERROR "signed immediate 16 must be in range [-16, 15]" - VADCVIM $-17, V2, V0, V3 // ERROR "signed immediate -17 must be in range [-16, 15]" - VMADCVVM X10, V2, V0, V3 // ERROR "expected vector register in vs1 position" - VMADCVXM V1, V2, V0, V3 // ERROR "expected integer register in rs1 position" - VMADCVIM $16, V2, V0, V3 // ERROR "signed immediate 16 must be in range [-16, 15]" - VMADCVIM $-17, V2, V0, V3 // ERROR "signed immediate -17 must be in range [-16, 15]" - VMADCVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VMADCVV V1, V2, V0, V3 // ERROR "expected no register in rs3" - VMADCVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VMADCVX X10, V2, V0, V3 // ERROR "expected no register in rs3" - VMADCVI $16, V2, V3 // ERROR "signed immediate 16 must be in range [-16, 15]" - VMADCVI $-17, V2, V3 // ERROR "signed immediate -17 must be in range [-16, 15]" - VMADCVI $15, V2, V0, V3 // ERROR "expected no register in rs3" - VSBCVVM X10, V2, V0, V3 // ERROR "expected vector register in vs1 position" - VSBCVXM V1, V2, V0, V3 // ERROR "expected integer register in rs1 position" - VMSBCVVM X10, V2, V0, V3 // ERROR "expected vector register in vs1 position" - VMSBCVXM V1, V2, V0, V3 // ERROR "expected integer register in rs1 position" - VMSBCVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VMSBCVV V1, V2, V0, V3 // ERROR "expected no register in rs3" - VMSBCVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VMSBCVX X10, V2, V0, V3 // ERROR "expected no register in rs3" - VANDVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VANDVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VANDVI $16, V2, V3 // ERROR "signed immediate 16 must be in range [-16, 15]" - VANDVI $-17, V2, V3 // ERROR "signed immediate -17 must be in range [-16, 15]" - VORVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VORVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VORVI $16, V2, V3 // ERROR "signed immediate 16 must be in range [-16, 15]" - VORVI $-17, V2, V3 // ERROR "signed immediate -17 must be in range [-16, 15]" - VXORVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VXORVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VXORVI $16, V2, V3 // ERROR "signed immediate 16 must be in range [-16, 15]" - VXORVI $-17, V2, V3 // ERROR "signed immediate -17 must be in range [-16, 15]" - VNOTV V3 // ERROR "expected vector register in vd position" - VNOTV X10, V3 // ERROR "expected vector register in vs2 position" - VSLLVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VSLLVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VSLLVI $32, V2, V3 // ERROR "unsigned immediate 32 must be in range [0, 31]" - VSLLVI $-1, V2, V3 // ERROR "unsigned immediate -1 must be in range [0, 31]" - VSRLVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VSRLVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VSRLVI $32, V2, V3 // ERROR "unsigned immediate 32 must be in range [0, 31]" - VSRLVI $-1, V2, V3 // ERROR "unsigned immediate -1 must be in range [0, 31]" - VSRAVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VSRAVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VSRAVI $32, V2, V3 // ERROR "unsigned immediate 32 must be in range [0, 31]" - VSRAVI $-1, V2, V3 // ERROR "unsigned immediate -1 must be in range [0, 31]" - VNSRLWV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VNSRLWX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VNSRLWI $32, V2, V3 // ERROR "unsigned immediate 32 must be in range [0, 31]" - VNSRLWI $-1, V2, V3 // ERROR "unsigned immediate -1 must be in range [0, 31]" - VNSRAWV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VNSRAWX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VNSRAWI $32, V2, V3 // ERROR "unsigned immediate 32 must be in range [0, 31]" - VNSRAWI $-1, V2, V3 // ERROR "unsigned immediate -1 must be in range [0, 31]" - VNCVTXXW X10, V3 // ERROR "expected vector register in vs2 position" - VMSEQVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VMSEQVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VMSEQVI $16, V2, V3 // ERROR "signed immediate 16 must be in range [-16, 15]" - VMSEQVI $-17, V2, V3 // ERROR "signed immediate -17 must be in range [-16, 15]" - VMSNEVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VMSNEVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VMSNEVI $16, V2, V3 // ERROR "signed immediate 16 must be in range [-16, 15]" - VMSNEVI $-17, V2, V3 // ERROR "signed immediate -17 must be in range [-16, 15]" - VMSLTUVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VMSLTUVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VMSLTVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VMSLTVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VMSLEUVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VMSLEUVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VMSLEUVI $16, V2, V3 // ERROR "signed immediate 16 must be in range [-16, 15]" - VMSLEUVI $-17, V2, V3 // ERROR "signed immediate -17 must be in range [-16, 15]" - VMSLEVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VMSLEVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VMSLEVI $16, V2, V3 // ERROR "signed immediate 16 must be in range [-16, 15]" - VMSLEVI $-17, V2, V3 // ERROR "signed immediate -17 must be in range [-16, 15]" - VMSGTUVV X10, V2, V3 // ERROR "expected vector register in vs2 position" - VMSGTUVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VMSGTUVI $16, V2, V3 // ERROR "signed immediate 16 must be in range [-16, 15]" - VMSGTUVI $-17, V2, V3 // ERROR "signed immediate -17 must be in range [-16, 15]" - VMSGTVV X10, V2, V3 // ERROR "expected vector register in vs2 position" - VMSGTVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VMSGTVI $16, V2, V3 // ERROR "signed immediate 16 must be in range [-16, 15]" - VMSGTVI $-17, V2, V3 // ERROR "signed immediate -17 must be in range [-16, 15]" - VMSGEVV X10, V2, V3 // ERROR "expected vector register in vs2 position" - VMSGEUVV X10, V2, V3 // ERROR "expected vector register in vs2 position" - VMSLTVI $17, V2, V3 // ERROR "signed immediate 16 must be in range [-16, 15]" - VMSLTVI $-16, V2, V3 // ERROR "signed immediate -17 must be in range [-16, 15]" - VMSLTUVI $17, V2, V3 // ERROR "signed immediate 16 must be in range [-16, 15]" - VMSLTUVI $-16, V2, V3 // ERROR "signed immediate -17 must be in range [-16, 15]" - VMSGEVI $17, V2, V3 // ERROR "signed immediate 16 must be in range [-16, 15]" - VMSGEVI $-16, V2, V3 // ERROR "signed immediate -17 must be in range [-16, 15]" - VMSGEUVI $17, V2, V3 // ERROR "signed immediate 16 must be in range [-16, 15]" - VMSGEUVI $-16, V2, V3 // ERROR "signed immediate -17 must be in range [-16, 15]" - VMINUVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VMINUVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VMINVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VMINVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VMAXUVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VMAXUVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VMAXVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VMAXVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VMULVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VMULVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VMULHVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VMULHVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VMULHUVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VMULHUVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VMULHSUVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VMULHSUVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VDIVUVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VDIVUVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VDIVVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VDIVVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VREMUVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VREMUVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VREMVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VREMVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VWMULVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VWMULVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VWMULUVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VWMULUVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VWMULSUVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VWMULSUVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VMACCVV V2, X10, V3 // ERROR "expected vector register in vs1 position" - VMACCVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VNMSACVV V2, X10, V3 // ERROR "expected vector register in vs1 position" - VNMSACVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VMADDVV V2, X10, V3 // ERROR "expected vector register in vs1 position" - VMADDVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VNMSUBVV V2, X10, V3 // ERROR "expected vector register in vs1 position" - VNMSUBVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VWMACCUVV V2, X10, V3 // ERROR "expected vector register in vs1 position" - VWMACCUVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VWMACCVV V2, X10, V3 // ERROR "expected vector register in vs1 position" - VWMACCVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VWMACCSUVV V2, X10, V3 // ERROR "expected vector register in vs1 position" - VWMACCSUVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VWMACCUSVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VMERGEVVM X10, V2, V0, V3 // ERROR "expected vector register in vs1 position" - VMERGEVXM V1, V2, V0, V3 // ERROR "expected integer register in rs1 position" - VMERGEVIM $16, V2, V0, V3 // ERROR "signed immediate 16 must be in range [-16, 15]" - VMERGEVIM $-17, V2, V0, V3 // ERROR "signed immediate -17 must be in range [-16, 15]" - VMVVV X10, V3 // ERROR "expected vector register in vs1 position" - VMVVX V1, V2 // ERROR "expected integer register in rs1 position" - VMVVI $16, V2 // ERROR "signed immediate 16 must be in range [-16, 15]" - VMVVI $-17, V2 // ERROR "signed immediate -17 must be in range [-16, 15]" - VSADDUVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VSADDUVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VSADDUVI $16, V2, V3 // ERROR "signed immediate 16 must be in range [-16, 15]" - VSADDUVI $-17, V2, V3 // ERROR "signed immediate -17 must be in range [-16, 15]" - VSSUBUVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VSSUBUVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VAADDUVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VAADDUVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VAADDVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VAADDVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VASUBUVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VASUBUVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VASUBVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VASUBVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VSMULVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VSMULVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VSSRLVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VSSRLVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VSSRLVI $32, V2, V3 // ERROR "signed immediate 32 must be in range [0, 31]" - VSSRLVI $-1, V2, V3 // ERROR "signed immediate -1 must be in range [0, 31]" - VSSRAVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VSSRAVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VSSRAVI $32, V2, V3 // ERROR "signed immediate 32 must be in range [0, 31]" - VSSRAVI $-1, V2, V3 // ERROR "signed immediate -1 must be in range [0, 31]" - VNCLIPUWV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VNCLIPUWX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VNCLIPUWI $32, V2, V3 // ERROR "signed immediate 32 must be in range [0, 31]" - VNCLIPUWI $-1, V2, V3 // ERROR "signed immediate -1 must be in range [0, 31]" - VNCLIPWV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VNCLIPWX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VNCLIPWI $32, V2, V3 // ERROR "signed immediate 32 must be in range [0, 31]" - VNCLIPWI $-1, V2, V3 // ERROR "signed immediate -1 must be in range [0, 31]" - VFADDVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VFADDVF X10, V2, V3 // ERROR "expected float register in rs1 position" - VFSUBVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VFSUBVF X10, V2, V3 // ERROR "expected float register in rs1 position" - VFRSUBVF X10, V2, V3 // ERROR "expected float register in rs1 position" - VFWADDVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VFWADDVF X10, V2, V3 // ERROR "expected float register in rs1 position" - VFWSUBVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VFWSUBVF X10, V2, V3 // ERROR "expected float register in rs1 position" - VFWADDWV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VFWADDWF X10, V2, V3 // ERROR "expected float register in rs1 position" - VFWSUBWV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VFWSUBWF X10, V2, V3 // ERROR "expected float register in rs1 position" - VFMULVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VFMULVF X10, V2, V3 // ERROR "expected float register in rs1 position" - VFDIVVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VFDIVVF X10, V2, V3 // ERROR "expected float register in rs1 position" - VFRDIVVF X10, V2, V3 // ERROR "expected float register in rs1 position" - VFWMULVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VFWMULVF X10, V2, V3 // ERROR "expected float register in rs1 position" - VFMACCVV V2, X10, V3 // ERROR "expected vector register in vs1 position" - VFMACCVF V2, X10, V3 // ERROR "expected float register in rs1 position" - VFNMACCVV V2, X10, V3 // ERROR "expected vector register in vs1 position" - VFNMACCVF V2, X10, V3 // ERROR "expected float register in rs1 position" - VFMSACVV V2, X10, V3 // ERROR "expected vector register in vs1 position" - VFMSACVF V2, X10, V3 // ERROR "expected float register in rs1 position" - VFNMSACVV V2, X10, V3 // ERROR "expected vector register in vs1 position" - VFNMSACVF V2, X10, V3 // ERROR "expected float register in rs1 position" - VFMADDVV V2, X10, V3 // ERROR "expected vector register in vs1 position" - VFMADDVF V2, X10, V3 // ERROR "expected float register in rs1 position" - VFNMADDVV V2, X10, V3 // ERROR "expected vector register in vs1 position" - VFNMADDVF V2, X10, V3 // ERROR "expected float register in rs1 position" - VFMSUBVV V2, X10, V3 // ERROR "expected vector register in vs1 position" - VFMSUBVF V2, X10, V3 // ERROR "expected float register in rs1 position" - VFNMSUBVV V2, X10, V3 // ERROR "expected vector register in vs1 position" - VFNMSUBVF V2, X10, V3 // ERROR "expected float register in rs1 position" - VFWMACCVV V2, X10, V3 // ERROR "expected vector register in vs1 position" - VFWMACCVF V2, X10, V3 // ERROR "expected float register in rs1 position" - VFWNMACCVV V2, X10, V3 // ERROR "expected vector register in vs1 position" - VFWNMACCVF V2, X10, V3 // ERROR "expected float register in rs1 position" - VFWMSACVV V2, X10, V3 // ERROR "expected vector register in vs1 position" - VFWMSACVF V2, X10, V3 // ERROR "expected float register in rs1 position" - VFWNMSACVV V2, X10, V3 // ERROR "expected vector register in vs1 position" - VFWNMSACVF V2, X10, V3 // ERROR "expected float register in rs1 position" - VFSQRTV X10, V3 // ERROR "expected vector register in vs2 position" - VFRSQRT7V X10, V3 // ERROR "expected vector register in vs2 position" - VFREC7V X10, V3 // ERROR "expected vector register in vs2 position" - VFMINVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VFMINVF X10, V2, V3 // ERROR "expected float register in rs1 position" - VFMAXVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VFMAXVF X10, V2, V3 // ERROR "expected float register in rs1 position" - VFSGNJVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VFSGNJVF X10, V2, V3 // ERROR "expected float register in rs1 position" - VFSGNJNVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VFSGNJNVF X10, V2, V3 // ERROR "expected float register in rs1 position" - VFSGNJXVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VFSGNJXVF X10, V2, V3 // ERROR "expected float register in rs1 position" - VFNEGV V2, X10 // ERROR "expected vector register in vd position" - VFABSV V2, X10 // ERROR "expected vector register in vd position" - VMFEQVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VMFEQVF X10, V2, V3 // ERROR "expected float register in rs1 position" - VMFNEVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VMFNEVF X10, V2, V3 // ERROR "expected float register in rs1 position" - VMFLTVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VMFLTVF X10, V2, V3 // ERROR "expected float register in rs1 position" - VMFLEVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VMFLEVF X10, V2, V3 // ERROR "expected float register in rs1 position" - VMFGTVF X10, V2, V3 // ERROR "expected float register in rs1 position" - VMFGEVF X10, V2, V3 // ERROR "expected float register in rs1 position" - VMFGTVV X10, V2, V3 // ERROR "expected vector register in vs2 position" - VMFGEVV X10, V2, V3 // ERROR "expected vector register in vs2 position" - VFCLASSV X10, V3 // ERROR "expected vector register in vs2 position" - VFMERGEVFM X10, V2, V0, V3 // ERROR "expected float register in rs1 position" - VFMVVF X10, V3 // ERROR "expected float register in rs1 position" - VFCVTXUFV X10, V3 // ERROR "expected vector register in vs2 position" - VFCVTXFV X10, V3 // ERROR "expected vector register in vs2 position" - VFCVTRTZXUFV X10, V3 // ERROR "expected vector register in vs2 position" - VFCVTRTZXFV X10, V3 // ERROR "expected vector register in vs2 position" - VFCVTFXUV X10, V3 // ERROR "expected vector register in vs2 position" - VFCVTFXV X10, V3 // ERROR "expected vector register in vs2 position" - VFWCVTXUFV X10, V3 // ERROR "expected vector register in vs2 position" - VFWCVTXFV X10, V3 // ERROR "expected vector register in vs2 position" - VFWCVTRTZXUFV X10, V3 // ERROR "expected vector register in vs2 position" - VFWCVTRTZXFV X10, V3 // ERROR "expected vector register in vs2 position" - VFWCVTFXUV X10, V3 // ERROR "expected vector register in vs2 position" - VFWCVTFXV X10, V3 // ERROR "expected vector register in vs2 position" - VFWCVTFFV X10, V3 // ERROR "expected vector register in vs2 position" - VFNCVTXUFW X10, V3 // ERROR "expected vector register in vs2 position" - VFNCVTXFW X10, V3 // ERROR "expected vector register in vs2 position" - VFNCVTRTZXUFW X10, V3 // ERROR "expected vector register in vs2 position" - VFNCVTRTZXFW X10, V3 // ERROR "expected vector register in vs2 position" - VFNCVTFXUW X10, V3 // ERROR "expected vector register in vs2 position" - VFNCVTFXW X10, V3 // ERROR "expected vector register in vs2 position" - VFNCVTFFW X10, V3 // ERROR "expected vector register in vs2 position" - VFNCVTRODFFW X10, V3 // ERROR "expected vector register in vs2 position" - VREDSUMVS X10, V2, V3 // ERROR "expected vector register in vs1 position" - VREDMAXUVS X10, V2, V3 // ERROR "expected vector register in vs1 position" - VREDMAXVS X10, V2, V3 // ERROR "expected vector register in vs1 position" - VREDMINUVS X10, V2, V3 // ERROR "expected vector register in vs1 position" - VREDMINVS X10, V2, V3 // ERROR "expected vector register in vs1 position" - VREDANDVS X10, V2, V3 // ERROR "expected vector register in vs1 position" - VREDORVS X10, V2, V3 // ERROR "expected vector register in vs1 position" - VREDXORVS X10, V2, V3 // ERROR "expected vector register in vs1 position" - VWREDSUMUVS X10, V2, V3 // ERROR "expected vector register in vs1 position" - VWREDSUMVS X10, V2, V3 // ERROR "expected vector register in vs1 position" - VFREDOSUMVS X10, V2, V3 // ERROR "expected vector register in vs1 position" - VFREDUSUMVS X10, V2, V3 // ERROR "expected vector register in vs1 position" - VFREDMAXVS X10, V2, V3 // ERROR "expected vector register in vs1 position" - VFREDMINVS X10, V2, V3 // ERROR "expected vector register in vs1 position" - VFWREDOSUMVS X10, V2, V3 // ERROR "expected vector register in vs1 position" - VFWREDUSUMVS X10, V2, V3 // ERROR "expected vector register in vs1 position" - VMANDMM X10, V2, V3 // ERROR "expected vector register in vs1 position" - VMNANDMM X10, V2, V3 // ERROR "expected vector register in vs1 position" - VMANDNMM X10, V2, V3 // ERROR "expected vector register in vs1 position" - VMXORMM X10, V2, V3 // ERROR "expected vector register in vs1 position" - VMORMM X10, V2, V3 // ERROR "expected vector register in vs1 position" - VMNORMM X10, V2, V3 // ERROR "expected vector register in vs1 position" - VMORNMM X10, V2, V3 // ERROR "expected vector register in vs1 position" - VMXNORMM X10, V2, V3 // ERROR "expected vector register in vs1 position" - VMMVM V3, X10 // ERROR "expected vector register in vd position" - VMNOTM V3, X10 // ERROR "expected vector register in vd position" - VCPOPM V2, V1 // ERROR "expected integer register in rd position" - VCPOPM X11, X10 // ERROR "expected vector register in vs2 position" - VFIRSTM V2, V1 // ERROR "expected integer register in rd position" - VFIRSTM X11, X10 // ERROR "expected vector register in vs2 position" - VMSBFM X10, V3 // ERROR "expected vector register in vs2 position" - VMSIFM X10, V3 // ERROR "expected vector register in vs2 position" - VMSOFM X10, V3 // ERROR "expected vector register in vs2 position" - VIOTAM X10, V3 // ERROR "expected vector register in vs2 position" - VIDV X10 // ERROR "expected vector register in vd position" - VMVXS X11, X10 // ERROR "expected vector register in vs2 position" - VMVXS V2, V1 // ERROR "expected integer register in rd position" - VMVSX X11, X10 // ERROR "expected vector register in vd position" - VMVSX V2, V1 // ERROR "expected integer register in rs2 position" - VFMVFS X10, F10 // ERROR "expected vector register in vs2 position" - VFMVFS V2, V1 // ERROR "expected float register in rd position" - VFMVSF X10, V2 // ERROR "expected float register in rs2 position" - VFMVSF V2, V1 // ERROR "expected float register in rs2 position" - VSLIDEUPVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VSLIDEUPVI $-1, V2, V3 // ERROR "unsigned immediate -1 must be in range [0, 31]" - VSLIDEUPVI $32, V2, V3 // ERROR "unsigned immediate 32 must be in range [0, 31]" - VSLIDEDOWNVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VSLIDEDOWNVI $-1, V2, V3 // ERROR "unsigned immediate -1 must be in range [0, 31]" - VSLIDEDOWNVI $32, V2, V3 // ERROR "unsigned immediate 32 must be in range [0, 31]" - VSLIDE1UPVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VFSLIDE1UPVF V1, V2, V3 // ERROR "expected float register in rs1 position" - VSLIDE1DOWNVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VFSLIDE1DOWNVF V1, V2, V3 // ERROR "expected float register in rs1 position" - VRGATHERVV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VRGATHEREI16VV X10, V2, V3 // ERROR "expected vector register in vs1 position" - VRGATHERVX V1, V2, V3 // ERROR "expected integer register in rs1 position" - VRGATHERVI $-1, V2, V3 // ERROR "unsigned immediate -1 must be in range [0, 31]" - VRGATHERVI $32, V2, V3 // ERROR "unsigned immediate 32 must be in range [0, 31]" - VCOMPRESSVM X10, V2, V3 // ERROR "expected vector register in vs1 position" - VMV1RV X10, V1 // ERROR "expected vector register in vs2 position" - VMV2RV X10, V10 // ERROR "expected vector register in vs2 position" - VMV4RV X10, V4 // ERROR "expected vector register in vs2 position" - VMV8RV X10, V0 // ERROR "expected vector register in vs2 position" + VSETVLI $32, E16, M1, TU, MU, X12 // ERROR "must be in range [0, 31] (5 bits)" + VSETVLI $-1, E32, M2, TA, MA, X12 // ERROR "must be in range [0, 31] (5 bits)" + VSETVL X10, X11 // ERROR "expected integer register in rs1 position" + VLE8V (X10), X10 // ERROR "expected vector register in vd position" + VLE8V (V1), V3 // ERROR "expected integer register in rs1 position" + VSE8V X10, (X10) // ERROR "expected vector register in vs1 position" + VSE8V V3, (V1) // ERROR "expected integer register in rd position" + VLSE8V (X10), V3 // ERROR "expected integer register in rs2 position" + VLSE8V (X10), X10, X11 // ERROR "expected vector register in vd position" + VLSE8V (V1), X10, V3 // ERROR "expected integer register in rs1 position" + VLSE8V (X10), V1, V0, V3 // ERROR "expected integer register in rs2 position" + VSSE8V V3, (X10) // ERROR "expected integer register in rs2 position" + VSSE8V X10, X11, (X10) // ERROR "expected vector register in vd position" + VSSE8V V3, X11, (V1) // ERROR "expected integer register in rs1 position" + VSSE8V V3, V1, V0, (X10) // ERROR "expected integer register in rs2 position" + VLUXEI8V (X10), V2, X11 // ERROR "expected vector register in vd position" + VLUXEI8V (X10), V2, X11 // ERROR "expected vector register in vd position" + VLUXEI8V (V1), V2, V3 // ERROR "expected integer register in rs1 position" + VLUXEI8V (X10), X11, V0, V3 // ERROR "expected vector register in vs2 position" + VSUXEI8V X10, V2, (X10) // ERROR "expected vector register in vd position" + VSUXEI8V V3, V2, (V1) // ERROR "expected integer register in rs1 position" + VSUXEI8V V3, X11, V0, (X10) // ERROR "expected vector register in vs2 position" + VLOXEI8V (X10), V2, X11 // ERROR "expected vector register in vd position" + VLOXEI8V (V1), V2, V3 // ERROR "expected integer register in rs1 position" + VLOXEI8V (X10), X11, V0, V3 // ERROR "expected vector register in vs2 position" + VSOXEI8V X10, V2, (X10) // ERROR "expected vector register in vd position" + VSOXEI8V V3, V2, (V1) // ERROR "expected integer register in rs1 position" + VSOXEI8V V3, X11, V0, (X10) // ERROR "expected vector register in vs2 position" + VL1RV (X10), X10 // ERROR "expected vector register in vd position" + VL1RV (V1), V3 // ERROR "expected integer register in rs1 position" + VS1RV X11, (X11) // ERROR "expected vector register in vs1 position" + VS1RV V3, (V1) // ERROR "expected integer register in rd position" + VADDVV V1, X10, V3 // ERROR "expected vector register in vs2 position" + VADDVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VADDVI $16, V4, V2 // ERROR "signed immediate 16 must be in range [-16, 15] (5 bits)" + VADDVI $-17, V4, V2 // ERROR "signed immediate -17 must be in range [-16, 15] (5 bits)" + VSUBVV V1, X10, V3 // ERROR "expected vector register in vs2 position" + VSUBVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VRSUBVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VRSUBVI $16, V4, V2 // ERROR "signed immediate 16 must be in range [-16, 15] (5 bits)" + VRSUBVI $-17, V4, V2 // ERROR "signed immediate -17 must be in range [-16, 15] (5 bits)" + VNEGV X10, V3 // ERROR "expected vector register in vs2 position" + VNEGV V2 // ERROR "expected vector register in vd position" + VWADDUVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VWADDUVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VWSUBUVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VWSUBUVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VWADDVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VWADDVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VWSUBVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VWSUBVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VWADDUWV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VWADDUWX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VWSUBUWV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VWSUBUWX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VWADDWV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VWADDWX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VWSUBWV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VWSUBWX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VWCVTXXV X10, V3 // ERROR "expected vector register in vs2 position" + VWCVTUXXV X10, V3 // ERROR "expected vector register in vs2 position" + VZEXTVF2 V2, V0, V3, V4 // ERROR "expected no register in rs3" + VZEXTVF2 X10, V3 // ERROR "expected vector register in vs2 position" + VSEXTVF2 V2, V0, V3, V4 // ERROR "expected no register in rs3" + VSEXTVF2 X10, V3 // ERROR "expected vector register in vs2 position" + VZEXTVF4 V2, V0, V3, V4 // ERROR "expected no register in rs3" + VZEXTVF4 X10, V3 // ERROR "expected vector register in vs2 position" + VSEXTVF4 V2, V0, V3, V4 // ERROR "expected no register in rs3" + VSEXTVF4 X10, V3 // ERROR "expected vector register in vs2 position" + VZEXTVF8 V2, V0, V3, V4 // ERROR "expected no register in rs3" + VZEXTVF8 X10, V3 // ERROR "expected vector register in vs2 position" + VSEXTVF8 V2, V0, V3, V4 // ERROR "expected no register in rs3" + VSEXTVF8 X10, V3 // ERROR "expected vector register in vs2 position" + VADCVVM X10, V2, V0, V3 // ERROR "expected vector register in vs1 position" + VADCVXM V1, V2, V0, V3 // ERROR "expected integer register in rs1 position" + VADCVIM $16, V2, V0, V3 // ERROR "signed immediate 16 must be in range [-16, 15]" + VADCVIM $-17, V2, V0, V3 // ERROR "signed immediate -17 must be in range [-16, 15]" + VMADCVVM X10, V2, V0, V3 // ERROR "expected vector register in vs1 position" + VMADCVXM V1, V2, V0, V3 // ERROR "expected integer register in rs1 position" + VMADCVIM $16, V2, V0, V3 // ERROR "signed immediate 16 must be in range [-16, 15]" + VMADCVIM $-17, V2, V0, V3 // ERROR "signed immediate -17 must be in range [-16, 15]" + VMADCVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VMADCVV V1, V2, V0, V3 // ERROR "expected no register in rs3" + VMADCVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VMADCVX X10, V2, V0, V3 // ERROR "expected no register in rs3" + VMADCVI $16, V2, V3 // ERROR "signed immediate 16 must be in range [-16, 15]" + VMADCVI $-17, V2, V3 // ERROR "signed immediate -17 must be in range [-16, 15]" + VMADCVI $15, V2, V0, V3 // ERROR "expected no register in rs3" + VSBCVVM X10, V2, V0, V3 // ERROR "expected vector register in vs1 position" + VSBCVXM V1, V2, V0, V3 // ERROR "expected integer register in rs1 position" + VMSBCVVM X10, V2, V0, V3 // ERROR "expected vector register in vs1 position" + VMSBCVXM V1, V2, V0, V3 // ERROR "expected integer register in rs1 position" + VMSBCVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VMSBCVV V1, V2, V0, V3 // ERROR "expected no register in rs3" + VMSBCVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VMSBCVX X10, V2, V0, V3 // ERROR "expected no register in rs3" + VANDVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VANDVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VANDVI $16, V2, V3 // ERROR "signed immediate 16 must be in range [-16, 15]" + VANDVI $-17, V2, V3 // ERROR "signed immediate -17 must be in range [-16, 15]" + VORVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VORVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VORVI $16, V2, V3 // ERROR "signed immediate 16 must be in range [-16, 15]" + VORVI $-17, V2, V3 // ERROR "signed immediate -17 must be in range [-16, 15]" + VXORVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VXORVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VXORVI $16, V2, V3 // ERROR "signed immediate 16 must be in range [-16, 15]" + VXORVI $-17, V2, V3 // ERROR "signed immediate -17 must be in range [-16, 15]" + VNOTV V3 // ERROR "expected vector register in vd position" + VNOTV X10, V3 // ERROR "expected vector register in vs2 position" + VSLLVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VSLLVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VSLLVI $32, V2, V3 // ERROR "unsigned immediate 32 must be in range [0, 31]" + VSLLVI $-1, V2, V3 // ERROR "unsigned immediate -1 must be in range [0, 31]" + VSRLVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VSRLVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VSRLVI $32, V2, V3 // ERROR "unsigned immediate 32 must be in range [0, 31]" + VSRLVI $-1, V2, V3 // ERROR "unsigned immediate -1 must be in range [0, 31]" + VSRAVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VSRAVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VSRAVI $32, V2, V3 // ERROR "unsigned immediate 32 must be in range [0, 31]" + VSRAVI $-1, V2, V3 // ERROR "unsigned immediate -1 must be in range [0, 31]" + VNSRLWV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VNSRLWX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VNSRLWI $32, V2, V3 // ERROR "unsigned immediate 32 must be in range [0, 31]" + VNSRLWI $-1, V2, V3 // ERROR "unsigned immediate -1 must be in range [0, 31]" + VNSRAWV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VNSRAWX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VNSRAWI $32, V2, V3 // ERROR "unsigned immediate 32 must be in range [0, 31]" + VNSRAWI $-1, V2, V3 // ERROR "unsigned immediate -1 must be in range [0, 31]" + VNCVTXXW X10, V3 // ERROR "expected vector register in vs2 position" + VMSEQVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VMSEQVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VMSEQVI $16, V2, V3 // ERROR "signed immediate 16 must be in range [-16, 15]" + VMSEQVI $-17, V2, V3 // ERROR "signed immediate -17 must be in range [-16, 15]" + VMSNEVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VMSNEVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VMSNEVI $16, V2, V3 // ERROR "signed immediate 16 must be in range [-16, 15]" + VMSNEVI $-17, V2, V3 // ERROR "signed immediate -17 must be in range [-16, 15]" + VMSLTUVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VMSLTUVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VMSLTVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VMSLTVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VMSLEUVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VMSLEUVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VMSLEUVI $16, V2, V3 // ERROR "signed immediate 16 must be in range [-16, 15]" + VMSLEUVI $-17, V2, V3 // ERROR "signed immediate -17 must be in range [-16, 15]" + VMSLEVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VMSLEVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VMSLEVI $16, V2, V3 // ERROR "signed immediate 16 must be in range [-16, 15]" + VMSLEVI $-17, V2, V3 // ERROR "signed immediate -17 must be in range [-16, 15]" + VMSGTUVV X10, V2, V3 // ERROR "expected vector register in vs2 position" + VMSGTUVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VMSGTUVI $16, V2, V3 // ERROR "signed immediate 16 must be in range [-16, 15]" + VMSGTUVI $-17, V2, V3 // ERROR "signed immediate -17 must be in range [-16, 15]" + VMSGTVV X10, V2, V3 // ERROR "expected vector register in vs2 position" + VMSGTVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VMSGTVI $16, V2, V3 // ERROR "signed immediate 16 must be in range [-16, 15]" + VMSGTVI $-17, V2, V3 // ERROR "signed immediate -17 must be in range [-16, 15]" + VMSGEVV X10, V2, V3 // ERROR "expected vector register in vs2 position" + VMSGEUVV X10, V2, V3 // ERROR "expected vector register in vs2 position" + VMSLTVI $17, V2, V3 // ERROR "signed immediate 16 must be in range [-16, 15]" + VMSLTVI $-16, V2, V3 // ERROR "signed immediate -17 must be in range [-16, 15]" + VMSLTUVI $17, V2, V3 // ERROR "signed immediate 16 must be in range [-16, 15]" + VMSLTUVI $-16, V2, V3 // ERROR "signed immediate -17 must be in range [-16, 15]" + VMSGEVI $17, V2, V3 // ERROR "signed immediate 16 must be in range [-16, 15]" + VMSGEVI $-16, V2, V3 // ERROR "signed immediate -17 must be in range [-16, 15]" + VMSGEUVI $17, V2, V3 // ERROR "signed immediate 16 must be in range [-16, 15]" + VMSGEUVI $-16, V2, V3 // ERROR "signed immediate -17 must be in range [-16, 15]" + VMINUVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VMINUVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VMINVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VMINVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VMAXUVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VMAXUVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VMAXVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VMAXVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VMULVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VMULVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VMULHVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VMULHVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VMULHUVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VMULHUVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VMULHSUVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VMULHSUVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VDIVUVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VDIVUVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VDIVVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VDIVVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VREMUVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VREMUVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VREMVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VREMVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VWMULVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VWMULVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VWMULUVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VWMULUVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VWMULSUVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VWMULSUVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VMACCVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VMACCVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VNMSACVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VNMSACVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VMADDVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VMADDVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VNMSUBVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VNMSUBVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VWMACCUVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VWMACCUVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VWMACCVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VWMACCVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VWMACCSUVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VWMACCSUVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VWMACCUSVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VMERGEVVM X10, V2, V0, V3 // ERROR "expected vector register in vs1 position" + VMERGEVXM V1, V2, V0, V3 // ERROR "expected integer register in rs1 position" + VMERGEVIM $16, V2, V0, V3 // ERROR "signed immediate 16 must be in range [-16, 15]" + VMERGEVIM $-17, V2, V0, V3 // ERROR "signed immediate -17 must be in range [-16, 15]" + VMVVV X10, V3 // ERROR "expected vector register in vs1 position" + VMVVX V1, V2 // ERROR "expected integer register in rs1 position" + VMVVI $16, V2 // ERROR "signed immediate 16 must be in range [-16, 15]" + VMVVI $-17, V2 // ERROR "signed immediate -17 must be in range [-16, 15]" + VSADDUVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VSADDUVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VSADDUVI $16, V2, V3 // ERROR "signed immediate 16 must be in range [-16, 15]" + VSADDUVI $-17, V2, V3 // ERROR "signed immediate -17 must be in range [-16, 15]" + VSSUBUVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VSSUBUVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VAADDUVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VAADDUVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VAADDVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VAADDVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VASUBUVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VASUBUVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VASUBVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VASUBVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VSMULVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VSMULVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VSSRLVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VSSRLVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VSSRLVI $32, V2, V3 // ERROR "signed immediate 32 must be in range [0, 31]" + VSSRLVI $-1, V2, V3 // ERROR "signed immediate -1 must be in range [0, 31]" + VSSRAVV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VSSRAVX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VSSRAVI $32, V2, V3 // ERROR "signed immediate 32 must be in range [0, 31]" + VSSRAVI $-1, V2, V3 // ERROR "signed immediate -1 must be in range [0, 31]" + VNCLIPUWV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VNCLIPUWX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VNCLIPUWI $32, V2, V3 // ERROR "signed immediate 32 must be in range [0, 31]" + VNCLIPUWI $-1, V2, V3 // ERROR "signed immediate -1 must be in range [0, 31]" + VNCLIPWV X10, V2, V3 // ERROR "expected vector register in vs1 position" + VNCLIPWX V1, V2, V3 // ERROR "expected integer register in rs1 position" + VNCLIPWI $32, V2, V3 // ERROR "signed immediate 32 must be in range [0, 31]" + VNCLIPWI $-1, V2, V3 // ERROR "signed immediate -1 must be in range [0, 31]" RET diff --git a/src/cmd/cgo/internal/testsanitizers/asan_test.go b/src/cmd/cgo/internal/testsanitizers/asan_test.go index c2cdf7b6d645e8..f7f53da334e72f 100644 --- a/src/cmd/cgo/internal/testsanitizers/asan_test.go +++ b/src/cmd/cgo/internal/testsanitizers/asan_test.go @@ -135,9 +135,6 @@ func TestASANFuzz(t *testing.T) { if bytes.Contains(out, []byte("AddressSanitizer")) { t.Error(`output contains "AddressSanitizer", but should not`) } - if !bytes.Contains(out, []byte("FUZZ FAILED")) { - t.Error(`fuzz test did not fail with a "FUZZ FAILED" sentinel error`) - } } func mustHaveASAN(t *testing.T) *config { diff --git a/src/cmd/cgo/internal/testsanitizers/libfuzzer_test.go b/src/cmd/cgo/internal/testsanitizers/libfuzzer_test.go index 9f548d66eace03..85c8f7bbfbedda 100644 --- a/src/cmd/cgo/internal/testsanitizers/libfuzzer_test.go +++ b/src/cmd/cgo/internal/testsanitizers/libfuzzer_test.go @@ -95,8 +95,6 @@ func libFuzzerSupported(goos, goarch string) bool { default: return false } - case "loong64": - return true default: return false } diff --git a/src/cmd/cgo/internal/testsanitizers/testdata/asan_fuzz_test.go b/src/cmd/cgo/internal/testsanitizers/testdata/asan_fuzz_test.go index 1a51819d7d70ad..fb7ebd40780df8 100644 --- a/src/cmd/cgo/internal/testsanitizers/testdata/asan_fuzz_test.go +++ b/src/cmd/cgo/internal/testsanitizers/testdata/asan_fuzz_test.go @@ -24,7 +24,7 @@ func FuzzReverse(f *testing.F) { r1 := Reverse(s) r2 := Reverse(r1) if s != r2 { - t.Errorf("FUZZ FAILED: got %q want %q", r2, s) + t.Errorf("got %q want %q", r2, s) } }) } diff --git a/src/cmd/compile/default.pgo b/src/cmd/compile/default.pgo index 2c2588704f3f6e..65c28706ea54aa 100644 Binary files a/src/cmd/compile/default.pgo and b/src/cmd/compile/default.pgo differ diff --git a/src/cmd/compile/internal/amd64/ssa.go b/src/cmd/compile/internal/amd64/ssa.go index 3af513773d3b2e..c97cdbd5c049de 100644 --- a/src/cmd/compile/internal/amd64/ssa.go +++ b/src/cmd/compile/internal/amd64/ssa.go @@ -1154,31 +1154,6 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p.To.Type = obj.TYPE_REG p.To.Reg = v.Reg0() - case ssa.OpAMD64ADDQconstflags, ssa.OpAMD64ADDLconstflags: - p := s.Prog(v.Op.Asm()) - p.From.Type = obj.TYPE_CONST - p.From.Offset = v.AuxInt - // Note: the inc/dec instructions do not modify - // the carry flag like add$1 / sub$1 do. - // We currently never use the CF/OF flags from - // these instructions, so that is ok. - switch { - case p.As == x86.AADDQ && p.From.Offset == 1: - p.As = x86.AINCQ - p.From.Type = obj.TYPE_NONE - case p.As == x86.AADDQ && p.From.Offset == -1: - p.As = x86.ADECQ - p.From.Type = obj.TYPE_NONE - case p.As == x86.AADDL && p.From.Offset == 1: - p.As = x86.AINCL - p.From.Type = obj.TYPE_NONE - case p.As == x86.AADDL && p.From.Offset == -1: - p.As = x86.ADECL - p.From.Type = obj.TYPE_NONE - } - p.To.Type = obj.TYPE_REG - p.To.Reg = v.Reg0() - case ssa.OpAMD64BSFQ, ssa.OpAMD64BSRQ, ssa.OpAMD64BSFL, ssa.OpAMD64BSRL, ssa.OpAMD64SQRTSD, ssa.OpAMD64SQRTSS: p := s.Prog(v.Op.Asm()) p.From.Type = obj.TYPE_REG diff --git a/src/cmd/compile/internal/base/debug.go b/src/cmd/compile/internal/base/debug.go index 10393e773c366d..7bcbcb3e2c0cb6 100644 --- a/src/cmd/compile/internal/base/debug.go +++ b/src/cmd/compile/internal/base/debug.go @@ -29,7 +29,6 @@ type DebugFlags struct { DumpPtrs int `help:"show Node pointers values in dump output"` DwarfInl int `help:"print information about DWARF inlined function creation"` EscapeMutationsCalls int `help:"print extra escape analysis diagnostics about mutations and calls" concurrent:"ok"` - EscapeDebug int `help:"print information about escape analysis and resulting optimizations" concurrent:"ok"` Export int `help:"print export data"` FIPSHash string `help:"hash value for FIPS debugging" concurrent:"ok"` Fmahash string `help:"hash value for use in debugging platform-dependent multiply-add use" concurrent:"ok"` diff --git a/src/cmd/compile/internal/bitvec/bv.go b/src/cmd/compile/internal/bitvec/bv.go index d3133dcd2dc679..aab10433c8f181 100644 --- a/src/cmd/compile/internal/bitvec/bv.go +++ b/src/cmd/compile/internal/bitvec/bv.go @@ -196,5 +196,7 @@ func (bv BitVec) String() string { } func (bv BitVec) Clear() { - clear(bv.B) + for i := range bv.B { + bv.B[i] = 0 + } } diff --git a/src/cmd/compile/internal/escape/call.go b/src/cmd/compile/internal/escape/call.go index 58c44eb9bbd3ce..1d7a0c90893c67 100644 --- a/src/cmd/compile/internal/escape/call.go +++ b/src/cmd/compile/internal/escape/call.go @@ -40,7 +40,6 @@ func (e *escape) call(ks []hole, call ir.Node) { var fn *ir.Name switch call.Op() { case ir.OCALLFUNC: - // TODO(thepudds): use an ir.ReassignOracle here. v := ir.StaticValue(call.Fun) fn = ir.StaticCalleeName(v) } @@ -84,19 +83,15 @@ func (e *escape) call(ks []hole, call ir.Node) { argument(e.tagHole(ks, fn, param), arg) } - // internal/abi.EscapeNonString forces its argument to be on - // the heap, if it contains a non-string pointer. - // This is used in hash/maphash.Comparable, where we cannot + // hash/maphash.escapeForHash forces its argument to be on + // the heap, if it contains a non-string pointer. We cannot // hash pointers to local variables, as the address of the // local variable might change on stack growth. // Strings are okay as the hash depends on only the content, // not the pointer. - // This is also used in unique.clone, to model the data flow - // edge on the value with strings excluded, because strings - // are cloned (by content). // The actual call we match is - // internal/abi.EscapeNonString[go.shape.T](dict, go.shape.T) - if fn != nil && fn.Sym().Pkg.Path == "internal/abi" && strings.HasPrefix(fn.Sym().Name, "EscapeNonString[") { + // hash/maphash.escapeForHash[go.shape.T](dict, go.shape.T) + if fn != nil && fn.Sym().Pkg.Path == "hash/maphash" && strings.HasPrefix(fn.Sym().Name, "escapeForHash[") { ps := fntype.Params() if len(ps) == 2 && ps[1].Type.IsShape() { if !hasNonStringPointers(ps[1].Type) { @@ -164,14 +159,6 @@ func (e *escape) call(ks []hole, call ir.Node) { } e.discard(call.RType) - // Model the new backing store that might be allocated by append. - // Its address flows to the result. - // Users of escape analysis can look at the escape information for OAPPEND - // and use that to decide where to allocate the backing store. - backingStore := e.spill(ks[0], call) - // As we have a boolean to prevent reuse, we can treat these allocations as outside any loops. - backingStore.dst.loopDepth = 0 - case ir.OCOPY: call := call.(*ir.BinaryExpr) argument(e.mutatorHole(), call.X) diff --git a/src/cmd/compile/internal/escape/escape.go b/src/cmd/compile/internal/escape/escape.go index 06dee7ec41bf92..d6f0708a7f17ef 100644 --- a/src/cmd/compile/internal/escape/escape.go +++ b/src/cmd/compile/internal/escape/escape.go @@ -6,8 +6,6 @@ package escape import ( "fmt" - "go/constant" - "go/token" "cmd/compile/internal/base" "cmd/compile/internal/ir" @@ -88,9 +86,8 @@ import ( // A batch holds escape analysis state that's shared across an entire // batch of functions being analyzed at once. type batch struct { - allLocs []*location - closures []closure - reassignOracles map[*ir.Func]*ir.ReassignOracle + allLocs []*location + closures []closure heapLoc location mutatorLoc location @@ -132,7 +129,6 @@ func Batch(fns []*ir.Func, recursive bool) { b.heapLoc.attrs = attrEscapes | attrPersists | attrMutates | attrCalls b.mutatorLoc.attrs = attrMutates b.calleeLoc.attrs = attrCalls - b.reassignOracles = make(map[*ir.Func]*ir.ReassignOracle) // Construct data-flow graph from syntax trees. for _, fn := range fns { @@ -158,11 +154,6 @@ func Batch(fns []*ir.Func, recursive bool) { b.closures = nil for _, loc := range b.allLocs { - // Try to replace some non-constant expressions with literals. - b.rewriteWithLiterals(loc.n, loc.curfn) - - // Check if the node must be heap allocated for certain reasons - // such as OMAKESLICE for a large slice. if why := HeapAllocReason(loc.n); why != "" { b.flow(b.heapHole().addr(loc.n, why), loc) } @@ -315,11 +306,7 @@ func (b *batch) finish(fns []*ir.Func) { } } else { if base.Flag.LowerM != 0 && !goDeferWrapper { - if n.Op() == ir.OAPPEND { - base.WarnfAt(n.Pos(), "append escapes to heap") - } else { - base.WarnfAt(n.Pos(), "%v escapes to heap", n) - } + base.WarnfAt(n.Pos(), "%v escapes to heap", n) } if logopt.Enabled() { var e_curfn *ir.Func // TODO(mdempsky): Fix. @@ -329,11 +316,7 @@ func (b *batch) finish(fns []*ir.Func) { n.SetEsc(ir.EscHeap) } else { if base.Flag.LowerM != 0 && n.Op() != ir.ONAME && !goDeferWrapper { - if n.Op() == ir.OAPPEND { - base.WarnfAt(n.Pos(), "append does not escape") - } else { - base.WarnfAt(n.Pos(), "%v does not escape", n) - } + base.WarnfAt(n.Pos(), "%v does not escape", n) } n.SetEsc(ir.EscNone) if !loc.hasAttr(attrPersists) { @@ -524,101 +507,3 @@ func (b *batch) reportLeaks(pos src.XPos, name string, esc leaks, sig *types.Typ base.WarnfAt(pos, "%v does not escape, mutate, or call", name) } } - -// rewriteWithLiterals attempts to replace certain non-constant expressions -// within n with a literal if possible. -func (b *batch) rewriteWithLiterals(n ir.Node, fn *ir.Func) { - if n == nil || fn == nil { - return - } - if n.Op() != ir.OMAKESLICE && n.Op() != ir.OCONVIFACE { - return - } - if base.Flag.Cfg.CoverageInfo != nil { - // Avoid altering coverage results. - return - } - - // Look up a cached ReassignOracle for the function, lazily computing one if needed. - ro := b.reassignOracle(fn) - if ro == nil { - base.Fatalf("no ReassignOracle for function %v with closure parent %v", fn, fn.ClosureParent) - } - - switch n.Op() { - case ir.OMAKESLICE: - // Check if we can replace a non-constant argument to make with - // a literal to allow for this slice to be stack allocated if otherwise allowed. - n := n.(*ir.MakeExpr) - - r := &n.Cap - if n.Cap == nil { - r = &n.Len - } - - if s := ro.StaticValue(*r); s.Op() == ir.OLITERAL { - lit, ok := s.(*ir.BasicLit) - if !ok || lit.Val().Kind() != constant.Int { - base.Fatalf("unexpected BasicLit Kind") - } - if constant.Compare(lit.Val(), token.GEQ, constant.MakeInt64(0)) { - *r = lit - } - } - case ir.OCONVIFACE: - // Check if we can replace a non-constant expression in an interface conversion with - // a literal to avoid heap allocating the underlying interface value. - conv := n.(*ir.ConvExpr) - if conv.X.Op() != ir.OLITERAL && !conv.X.Type().IsInterface() { - v := ro.StaticValue(conv.X) - if v != nil && v.Op() == ir.OLITERAL && ir.ValidTypeForConst(conv.X.Type(), v.Val()) { - if base.Debug.EscapeDebug >= 3 { - base.WarnfAt(n.Pos(), "rewriting OCONVIFACE value from %v (%v) to %v (%v)", conv.X, conv.X.Type(), v, v.Type()) - } - v := v.(*ir.BasicLit) - conv.X = ir.NewBasicLit(conv.X.Pos(), conv.X.Type(), v.Val()) - typecheck.Expr(conv) - } - } - } -} - -// reassignOracle returns an initialized *ir.ReassignOracle for fn. -// If fn is a closure, it returns the ReassignOracle for the ultimate parent. -// -// A new ReassignOracle is initialized lazily if needed, and the result -// is cached to reduce duplicative work of preparing a ReassignOracle. -func (b *batch) reassignOracle(fn *ir.Func) *ir.ReassignOracle { - if ro, ok := b.reassignOracles[fn]; ok { - return ro // Hit. - } - - // For closures, we want the ultimate parent's ReassignOracle, - // so walk up the parent chain, if any. - f := fn - for f.ClosureParent != nil && !f.ClosureParent.IsPackageInit() { - f = f.ClosureParent - } - - if f != fn { - // We found a parent. - ro := b.reassignOracles[f] - if ro != nil { - // Hit, via a parent. Before returning, store this ro for the original fn as well. - b.reassignOracles[fn] = ro - return ro - } - } - - // Miss. We did not find a ReassignOracle for fn or a parent, so lazily create one. - ro := &ir.ReassignOracle{} - ro.Init(f) - - // Cache the answer for the original fn. - b.reassignOracles[fn] = ro - if f != fn { - // Cache for the parent as well. - b.reassignOracles[f] = ro - } - return ro -} diff --git a/src/cmd/compile/internal/escape/graph.go b/src/cmd/compile/internal/escape/graph.go index 0ffb4a0bb5a4de..75e2546a7b7a06 100644 --- a/src/cmd/compile/internal/escape/graph.go +++ b/src/cmd/compile/internal/escape/graph.go @@ -62,14 +62,9 @@ type location struct { dst *location dstEdgeIdx int - // queuedWalkAll is used by walkAll to track whether this location is - // in its work queue. - queuedWalkAll bool - - // queuedWalkOne is used by walkOne to track whether this location is - // in its work queue. The value is the walkgen when this location was - // last queued for walkOne, or 0 if it's not currently queued. - queuedWalkOne uint32 + // queued is used by walkAll to track whether this location is + // in the walk queue. + queued bool // attrs is a bitset of location attributes. attrs locAttr @@ -80,8 +75,6 @@ type location struct { captured bool // has a closure captured this variable? reassigned bool // has this variable been reassigned? addrtaken bool // has this variable's address been taken? - param bool // is this variable a parameter (ONAME of class ir.PPARAM)? - paramOut bool // is this variable an out parameter (ONAME of class ir.PPARAMOUT)? } type locAttr uint8 @@ -139,6 +132,35 @@ func (l *location) leakTo(sink *location, derefs int) { l.paramEsc.AddHeap(derefs) } +// leakTo records that parameter l leaks to sink. +func (b *batch) leakTo(l, sink *location, derefs int) { + if (logopt.Enabled() || base.Flag.LowerM >= 2) && !l.hasAttr(attrEscapes) { + if base.Flag.LowerM >= 2 { + fmt.Printf("%s: parameter %v leaks to %s with derefs=%d:\n", base.FmtPos(l.n.Pos()), l.n, b.explainLoc(sink), derefs) + } + explanation := b.explainPath(sink, l) + if logopt.Enabled() { + var e_curfn *ir.Func // TODO(mdempsky): Fix. + logopt.LogOpt(l.n.Pos(), "leak", "escape", ir.FuncName(e_curfn), + fmt.Sprintf("parameter %v leaks to %s with derefs=%d", l.n, b.explainLoc(sink), derefs), explanation) + } + } + + // If sink is a result parameter that doesn't escape (#44614) + // and we can fit return bits into the escape analysis tag, + // then record as a result leak. + if !sink.hasAttr(attrEscapes) && sink.isName(ir.PPARAMOUT) && sink.curfn == l.curfn { + if ri := sink.resultIndex - 1; ri < numEscResults { + // Leak to result parameter. + l.paramEsc.AddResult(ri, derefs) + return + } + } + + // Otherwise, record as heap leak. + l.paramEsc.AddHeap(derefs) +} + func (l *location) isName(c ir.Class) bool { return l.n != nil && l.n.Op() == ir.ONAME && l.n.(*ir.Name).Class == c } @@ -212,7 +234,7 @@ func (b *batch) flow(k hole, src *location) { if base.Flag.LowerM >= 2 || logopt.Enabled() { pos := base.FmtPos(src.n.Pos()) if base.Flag.LowerM >= 2 { - fmt.Printf("%s: %v escapes to heap in %v:\n", pos, src.n, ir.FuncName(src.curfn)) + fmt.Printf("%s: %v escapes to heap:\n", pos, src.n) } explanation := b.explainFlow(pos, dst, src, k.derefs, k.notes, []*logopt.LoggedOpt{}) if logopt.Enabled() { @@ -259,12 +281,6 @@ func (e *escape) newLoc(n ir.Node, persists bool) *location { curfn: e.curfn, loopDepth: e.loopDepth, } - if loc.isName(ir.PPARAM) { - loc.param = true - } else if loc.isName(ir.PPARAMOUT) { - loc.paramOut = true - } - if persists { loc.attrs |= attrPersists } diff --git a/src/cmd/compile/internal/escape/solve.go b/src/cmd/compile/internal/escape/solve.go index e2ca3eabda99ad..2002f2fbe41f3e 100644 --- a/src/cmd/compile/internal/escape/solve.go +++ b/src/cmd/compile/internal/escape/solve.go @@ -10,7 +10,6 @@ import ( "cmd/compile/internal/logopt" "cmd/internal/src" "fmt" - "math/bits" "strings" ) @@ -25,41 +24,28 @@ func (b *batch) walkAll() { // !persists->persists and !escapes->escapes, which can each // happen at most once. So we take Θ(len(e.allLocs)) walks. - // Queue of locations to walk. Has enough room for b.allLocs - // plus b.heapLoc, b.mutatorLoc, b.calleeLoc. - todo := newQueue(len(b.allLocs) + 3) - + // LIFO queue, has enough room for e.allLocs and e.heapLoc. + todo := make([]*location, 0, len(b.allLocs)+1) enqueue := func(loc *location) { - if !loc.queuedWalkAll { - loc.queuedWalkAll = true - if loc.hasAttr(attrEscapes) { - // Favor locations that escape to the heap, - // which in some cases allows attrEscape to - // propagate faster. - todo.pushFront(loc) - } else { - todo.pushBack(loc) - } + if !loc.queued { + todo = append(todo, loc) + loc.queued = true } } for _, loc := range b.allLocs { - todo.pushFront(loc) - // TODO(thepudds): clean up setting queuedWalkAll. - loc.queuedWalkAll = true + enqueue(loc) } - todo.pushFront(&b.mutatorLoc) - todo.pushFront(&b.calleeLoc) - todo.pushFront(&b.heapLoc) - - b.mutatorLoc.queuedWalkAll = true - b.calleeLoc.queuedWalkAll = true - b.heapLoc.queuedWalkAll = true + enqueue(&b.mutatorLoc) + enqueue(&b.calleeLoc) + enqueue(&b.heapLoc) var walkgen uint32 - for todo.len() > 0 { - root := todo.popFront() - root.queuedWalkAll = false + for len(todo) > 0 { + root := todo[len(todo)-1] + todo = todo[:len(todo)-1] + root.queued = false + walkgen++ b.walkOne(root, walkgen, enqueue) } @@ -91,12 +77,10 @@ func (b *batch) walkOne(root *location, walkgen uint32, enqueue func(*location)) } } - todo := newQueue(1) - todo.pushFront(root) - - for todo.len() > 0 { - l := todo.popFront() - l.queuedWalkOne = 0 // no longer queued for walkOne + todo := []*location{root} // LIFO queue + for len(todo) > 0 { + l := todo[len(todo)-1] + todo = todo[:len(todo)-1] derefs := l.derefs var newAttrs locAttr @@ -116,7 +100,7 @@ func (b *batch) walkOne(root *location, walkgen uint32, enqueue func(*location)) if b.outlives(root, l) { if !l.hasAttr(attrEscapes) && (logopt.Enabled() || base.Flag.LowerM >= 2) { if base.Flag.LowerM >= 2 { - fmt.Printf("%s: %v escapes to heap in %v:\n", base.FmtPos(l.n.Pos()), l.n, ir.FuncName(l.curfn)) + fmt.Printf("%s: %v escapes to heap:\n", base.FmtPos(l.n.Pos()), l.n) } explanation := b.explainPath(root, l) if logopt.Enabled() { @@ -142,11 +126,11 @@ func (b *batch) walkOne(root *location, walkgen uint32, enqueue func(*location)) // corresponding result parameter, then record // that value flow for tagging the function // later. - if l.param { + if l.isName(ir.PPARAM) { if b.outlives(root, l) { if !l.hasAttr(attrEscapes) && (logopt.Enabled() || base.Flag.LowerM >= 2) { if base.Flag.LowerM >= 2 { - fmt.Printf("%s: parameter %v leaks to %s for %v with derefs=%d:\n", base.FmtPos(l.n.Pos()), l.n, b.explainLoc(root), ir.FuncName(l.curfn), derefs) + fmt.Printf("%s: parameter %v leaks to %s with derefs=%d:\n", base.FmtPos(l.n.Pos()), l.n, b.explainLoc(root), derefs) } explanation := b.explainPath(root, l) if logopt.Enabled() { @@ -183,14 +167,7 @@ func (b *batch) walkOne(root *location, walkgen uint32, enqueue func(*location)) edge.src.derefs = d edge.src.dst = l edge.src.dstEdgeIdx = i - // Check if already queued in todo. - if edge.src.queuedWalkOne != walkgen { - edge.src.queuedWalkOne = walkgen // Mark queued for this walkgen. - - // Place at the back to possibly give time for - // other possible attribute changes to src. - todo.pushBack(edge.src) - } + todo = append(todo, edge.src) } } } @@ -234,7 +211,7 @@ func (b *batch) explainFlow(pos string, dst, srcloc *location, derefs int, notes } print := base.Flag.LowerM >= 2 - flow := fmt.Sprintf(" flow: %s ← %s%v:", b.explainLoc(dst), ops, b.explainLoc(srcloc)) + flow := fmt.Sprintf(" flow: %s = %s%v:", b.explainLoc(dst), ops, b.explainLoc(srcloc)) if print { fmt.Printf("%s:%s\n", pos, flow) } @@ -293,7 +270,7 @@ func (b *batch) outlives(l, other *location) bool { // We don't know what callers do with returned values, so // pessimistically we need to assume they flow to the heap and // outlive everything too. - if l.paramOut { + if l.isName(ir.PPARAMOUT) { // Exception: Closures can return locations allocated outside of // them without forcing them to the heap, if we can statically // identify all call sites. For example: @@ -333,65 +310,3 @@ func (b *batch) outlives(l, other *location) bool { return false } - -// queue implements a queue of locations for use in WalkAll and WalkOne. -// It supports pushing to front & back, and popping from front. -// TODO(thepudds): does cmd/compile have a deque or similar somewhere? -type queue struct { - locs []*location - head int // index of front element - tail int // next back element - elems int -} - -func newQueue(capacity int) *queue { - capacity = max(capacity, 2) - capacity = 1 << bits.Len64(uint64(capacity-1)) // round up to a power of 2 - return &queue{locs: make([]*location, capacity)} -} - -// pushFront adds an element to the front of the queue. -func (q *queue) pushFront(loc *location) { - if q.elems == len(q.locs) { - q.grow() - } - q.head = q.wrap(q.head - 1) - q.locs[q.head] = loc - q.elems++ -} - -// pushBack adds an element to the back of the queue. -func (q *queue) pushBack(loc *location) { - if q.elems == len(q.locs) { - q.grow() - } - q.locs[q.tail] = loc - q.tail = q.wrap(q.tail + 1) - q.elems++ -} - -// popFront removes the front of the queue. -func (q *queue) popFront() *location { - if q.elems == 0 { - return nil - } - loc := q.locs[q.head] - q.head = q.wrap(q.head + 1) - q.elems-- - return loc -} - -// grow doubles the capacity. -func (q *queue) grow() { - newLocs := make([]*location, len(q.locs)*2) - for i := range q.elems { - // Copy over our elements in order. - newLocs[i] = q.locs[q.wrap(q.head+i)] - } - q.locs = newLocs - q.head = 0 - q.tail = q.elems -} - -func (q *queue) len() int { return q.elems } -func (q *queue) wrap(i int) int { return i & (len(q.locs) - 1) } diff --git a/src/cmd/compile/internal/escape/utils.go b/src/cmd/compile/internal/escape/utils.go index 2718a7f841817e..b3ebe778f4a2fb 100644 --- a/src/cmd/compile/internal/escape/utils.go +++ b/src/cmd/compile/internal/escape/utils.go @@ -5,9 +5,12 @@ package escape import ( + "cmd/compile/internal/base" "cmd/compile/internal/ir" "cmd/compile/internal/typecheck" "cmd/compile/internal/types" + "go/constant" + "go/token" ) func isSliceSelfAssign(dst, src ir.Node) bool { @@ -207,9 +210,21 @@ func HeapAllocReason(n ir.Node) string { if n.Op() == ir.OMAKESLICE { n := n.(*ir.MakeExpr) - r := n.Cap + r := &n.Cap if n.Cap == nil { - r = n.Len + r = &n.Len + } + + // Try to determine static values of make() calls, to avoid allocating them on the heap. + // We are doing this in escape analysis, so that it happens after inlining and devirtualization. + if s := ir.StaticValue(*r); s.Op() == ir.OLITERAL { + lit, ok := s.(*ir.BasicLit) + if !ok || lit.Val().Kind() != constant.Int { + base.Fatalf("unexpected BasicLit Kind") + } + if constant.Compare(lit.Val(), token.GEQ, constant.MakeInt64(0)) { + *r = lit + } } elem := n.Type().Elem() @@ -217,7 +232,7 @@ func HeapAllocReason(n ir.Node) string { // TODO: stack allocate these? See #65685. return "zero-sized element" } - if !ir.IsSmallIntConst(r) { + if !ir.IsSmallIntConst(*r) { // For non-constant sizes, we do a hybrid approach: // // if cap <= K { @@ -234,7 +249,7 @@ func HeapAllocReason(n ir.Node) string { // Implementation is in ../walk/builtin.go:walkMakeSlice. return "" } - if ir.Int64Val(r) > ir.MaxImplicitStackVarSize/elem.Size() { + if ir.Int64Val(*r) > ir.MaxImplicitStackVarSize/elem.Size() { return "too large for stack" } } diff --git a/src/cmd/compile/internal/importer/ureader.go b/src/cmd/compile/internal/importer/ureader.go index 6012d283ac5731..2f8f174a939999 100644 --- a/src/cmd/compile/internal/importer/ureader.go +++ b/src/cmd/compile/internal/importer/ureader.go @@ -33,12 +33,12 @@ func ReadPackage(ctxt *types2.Context, imports map[string]*types2.Package, input imports: imports, enableAlias: true, - posBases: make([]*syntax.PosBase, input.NumElems(pkgbits.SectionPosBase)), - pkgs: make([]*types2.Package, input.NumElems(pkgbits.SectionPkg)), - typs: make([]types2.Type, input.NumElems(pkgbits.SectionType)), + posBases: make([]*syntax.PosBase, input.NumElems(pkgbits.RelocPosBase)), + pkgs: make([]*types2.Package, input.NumElems(pkgbits.RelocPkg)), + typs: make([]types2.Type, input.NumElems(pkgbits.RelocType)), } - r := pr.newReader(pkgbits.SectionMeta, pkgbits.PublicRootIdx, pkgbits.SyncPublic) + r := pr.newReader(pkgbits.RelocMeta, pkgbits.PublicRootIdx, pkgbits.SyncPublic) pkg := r.pkg() if r.Version().Has(pkgbits.HasInit) { @@ -52,7 +52,7 @@ func ReadPackage(ctxt *types2.Context, imports map[string]*types2.Package, input if r.Version().Has(pkgbits.DerivedFuncInstance) { assert(!r.Bool()) } - r.p.objIdx(r.Reloc(pkgbits.SectionObj)) + r.p.objIdx(r.Reloc(pkgbits.RelocObj)) assert(r.Len() == 0) } @@ -84,14 +84,14 @@ type readerTypeBound struct { boundIdx int } -func (pr *pkgReader) newReader(k pkgbits.SectionKind, idx pkgbits.Index, marker pkgbits.SyncMarker) *reader { +func (pr *pkgReader) newReader(k pkgbits.RelocKind, idx pkgbits.Index, marker pkgbits.SyncMarker) *reader { return &reader{ Decoder: pr.NewDecoder(k, idx, marker), p: pr, } } -func (pr *pkgReader) tempReader(k pkgbits.SectionKind, idx pkgbits.Index, marker pkgbits.SyncMarker) *reader { +func (pr *pkgReader) tempReader(k pkgbits.RelocKind, idx pkgbits.Index, marker pkgbits.SyncMarker) *reader { return &reader{ Decoder: pr.TempDecoder(k, idx, marker), p: pr, @@ -118,7 +118,7 @@ func (r *reader) pos() syntax.Pos { } func (r *reader) posBase() *syntax.PosBase { - return r.p.posBaseIdx(r.Reloc(pkgbits.SectionPosBase)) + return r.p.posBaseIdx(r.Reloc(pkgbits.RelocPosBase)) } func (pr *pkgReader) posBaseIdx(idx pkgbits.Index) *syntax.PosBase { @@ -127,7 +127,7 @@ func (pr *pkgReader) posBaseIdx(idx pkgbits.Index) *syntax.PosBase { } var b *syntax.PosBase { - r := pr.tempReader(pkgbits.SectionPosBase, idx, pkgbits.SyncPosBase) + r := pr.tempReader(pkgbits.RelocPosBase, idx, pkgbits.SyncPosBase) filename := r.String() @@ -150,7 +150,7 @@ func (pr *pkgReader) posBaseIdx(idx pkgbits.Index) *syntax.PosBase { func (r *reader) pkg() *types2.Package { r.Sync(pkgbits.SyncPkg) - return r.p.pkgIdx(r.Reloc(pkgbits.SectionPkg)) + return r.p.pkgIdx(r.Reloc(pkgbits.RelocPkg)) } func (pr *pkgReader) pkgIdx(idx pkgbits.Index) *types2.Package { @@ -160,7 +160,7 @@ func (pr *pkgReader) pkgIdx(idx pkgbits.Index) *types2.Package { return pkg } - pkg := pr.newReader(pkgbits.SectionPkg, idx, pkgbits.SyncPkgDef).doPkg() + pkg := pr.newReader(pkgbits.RelocPkg, idx, pkgbits.SyncPkgDef).doPkg() pr.pkgs[idx] = pkg return pkg } @@ -206,7 +206,7 @@ func (r *reader) typInfo() typeInfo { if r.Bool() { return typeInfo{idx: pkgbits.Index(r.Len()), derived: true} } - return typeInfo{idx: r.Reloc(pkgbits.SectionType), derived: false} + return typeInfo{idx: r.Reloc(pkgbits.RelocType), derived: false} } func (pr *pkgReader) typIdx(info typeInfo, dict *readerDict) types2.Type { @@ -225,7 +225,7 @@ func (pr *pkgReader) typIdx(info typeInfo, dict *readerDict) types2.Type { var typ types2.Type { - r := pr.tempReader(pkgbits.SectionType, idx, pkgbits.SyncTypeIdx) + r := pr.tempReader(pkgbits.RelocType, idx, pkgbits.SyncTypeIdx) r.dict = dict typ = r.doTyp() @@ -376,7 +376,7 @@ func (r *reader) obj() (types2.Object, []types2.Type) { assert(!r.Bool()) } - pkg, name := r.p.objIdx(r.Reloc(pkgbits.SectionObj)) + pkg, name := r.p.objIdx(r.Reloc(pkgbits.RelocObj)) obj := pkg.Scope().Lookup(name) targs := make([]types2.Type, r.Len()) @@ -392,7 +392,7 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types2.Package, string) { var objName string var tag pkgbits.CodeObj { - rname := pr.tempReader(pkgbits.SectionName, idx, pkgbits.SyncObject1) + rname := pr.tempReader(pkgbits.RelocName, idx, pkgbits.SyncObject1) objPkg, objName = rname.qualifiedIdent() assert(objName != "") @@ -409,7 +409,7 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types2.Package, string) { objPkg.Scope().InsertLazy(objName, func() types2.Object { dict := pr.objDictIdx(idx) - r := pr.newReader(pkgbits.SectionObj, idx, pkgbits.SyncObject1) + r := pr.newReader(pkgbits.RelocObj, idx, pkgbits.SyncObject1) r.dict = dict switch tag { @@ -470,7 +470,7 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types2.Package, string) { func (pr *pkgReader) objDictIdx(idx pkgbits.Index) *readerDict { var dict readerDict { - r := pr.tempReader(pkgbits.SectionObjDict, idx, pkgbits.SyncObject1) + r := pr.tempReader(pkgbits.RelocObjDict, idx, pkgbits.SyncObject1) if implicits := r.Len(); implicits != 0 { base.Fatalf("unexpected object with %v implicit type parameter(s)", implicits) @@ -484,7 +484,7 @@ func (pr *pkgReader) objDictIdx(idx pkgbits.Index) *readerDict { dict.derived = make([]derivedInfo, r.Len()) dict.derivedTypes = make([]types2.Type, len(dict.derived)) for i := range dict.derived { - dict.derived[i] = derivedInfo{idx: r.Reloc(pkgbits.SectionType)} + dict.derived[i] = derivedInfo{idx: r.Reloc(pkgbits.RelocType)} if r.Version().Has(pkgbits.DerivedInfoNeeded) { assert(!r.Bool()) } diff --git a/src/cmd/compile/internal/inline/inl.go b/src/cmd/compile/internal/inline/inl.go index 459c2498fc40da..e30de3d8c87d87 100644 --- a/src/cmd/compile/internal/inline/inl.go +++ b/src/cmd/compile/internal/inline/inl.go @@ -454,11 +454,6 @@ opSwitch: // generate code. cheap = true } - if strings.HasPrefix(fn, "EscapeNonString[") { - // internal/abi.EscapeNonString[T] is a compiler intrinsic - // implemented in the escape analysis phase. - cheap = true - } case "internal/runtime/sys": switch fn { case "GetCallerPC", "GetCallerSP": @@ -477,6 +472,12 @@ opSwitch: case "panicrangestate": cheap = true } + case "hash/maphash": + if strings.HasPrefix(fn, "escapeForHash[") { + // hash/maphash.escapeForHash[T] is a compiler intrinsic + // implemented in the escape analysis phase. + cheap = true + } } } // Special case for coverage counter updates; although @@ -785,7 +786,7 @@ func inlineCallCheck(callerfn *ir.Func, call *ir.CallExpr) (bool, bool) { if call.Op() != ir.OCALLFUNC { return false, false } - if call.GoDefer || call.NoInline { + if call.GoDefer { return false, false } @@ -800,10 +801,10 @@ func inlineCallCheck(callerfn *ir.Func, call *ir.CallExpr) (bool, bool) { } } - // internal/abi.EscapeNonString[T] is a compiler intrinsic implemented + // hash/maphash.escapeForHash[T] is a compiler intrinsic implemented // in the escape analysis phase. - if fn := ir.StaticCalleeName(call.Fun); fn != nil && fn.Sym().Pkg.Path == "internal/abi" && - strings.HasPrefix(fn.Sym().Name, "EscapeNonString[") { + if fn := ir.StaticCalleeName(call.Fun); fn != nil && fn.Sym().Pkg.Path == "hash/maphash" && + strings.HasPrefix(fn.Sym().Name, "escapeForHash[") { return false, true } @@ -1116,18 +1117,12 @@ func mkinlcall(callerfn *ir.Func, n *ir.CallExpr, fn *ir.Func, bigCaller, closur // Not a standard call. return } - - var nf = n.Fun - // Skips ir.OCONVNOPs, see issue #73716. - for nf.Op() == ir.OCONVNOP { - nf = nf.(*ir.ConvExpr).X - } - if nf.Op() != ir.OCLOSURE { - // Not a direct closure call or one with type conversion. + if n.Fun.Op() != ir.OCLOSURE { + // Not a direct closure call. return } - clo := nf.(*ir.ClosureExpr) + clo := n.Fun.(*ir.ClosureExpr) if !clo.Func.IsClosure() { // enqueueFunc will handle non closures anyways. return diff --git a/src/cmd/compile/internal/inline/interleaved/interleaved.go b/src/cmd/compile/internal/inline/interleaved/interleaved.go index 954cc306fc81d3..a884c1bc7375d4 100644 --- a/src/cmd/compile/internal/inline/interleaved/interleaved.go +++ b/src/cmd/compile/internal/inline/interleaved/interleaved.go @@ -279,12 +279,7 @@ func (s *inlClosureState) mark(n ir.Node) ir.Node { ok := match(n) - // can't wrap TailCall's child into ParenExpr - if t, ok := n.(*ir.TailCallStmt); ok { - ir.EditChildren(t.Call, s.mark) - } else { - ir.EditChildren(n, s.mark) - } + ir.EditChildren(n, s.mark) if ok { if p == nil { @@ -322,6 +317,23 @@ func (s *inlClosureState) unparenthesize() { n = paren.X } ir.EditChildren(n, unparen) + // special case for tail calls: if the tail call was inlined, transform + // the tail call to a return stmt if the inlined function was not void, + // otherwise replace it with the inlined expression followed by a return. + if tail, ok := n.(*ir.TailCallStmt); ok { + if inl, done := tail.Call.(*ir.InlinedCallExpr); done { + if len(inl.ReturnVars) != 0 { + ret := ir.NewReturnStmt(tail.Pos(), []ir.Node{inl}) + if len(inl.ReturnVars) > 1 { + typecheck.RewriteMultiValueCall(ret, inl) + } + n = ret + } else { + ret := ir.NewReturnStmt(tail.Pos(), nil) + n = ir.NewBlockStmt(tail.Pos(), []ir.Node{inl, ret}) + } + } + } return n } ir.EditChildren(s.fn, unparen) @@ -358,11 +370,9 @@ func (s *inlClosureState) fixpoint() bool { } func match(n ir.Node) bool { - switch n := n.(type) { + switch n.(type) { case *ir.CallExpr: return true - case *ir.TailCallStmt: - n.Call.NoInline = true // can't inline yet } return false } diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index 702adfdd84ef5e..cf56515a2c1647 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -191,7 +191,6 @@ type CallExpr struct { KeepAlive []*Name // vars to be kept alive until call returns IsDDD bool GoDefer bool // whether this call is part of a go or defer statement - NoInline bool // whether this call must not be inlined } func NewCallExpr(pos src.XPos, op Op, fun Node, args []Node) *CallExpr { @@ -854,10 +853,6 @@ func IsAddressable(n Node) bool { // // calling StaticValue on the "int(y)" expression returns the outer // "g()" expression. -// -// NOTE: StaticValue can return a result with a different type than -// n's type because it can traverse through OCONVNOP operations. -// TODO: consider reapplying OCONVNOP operations to the result. See https://go.dev/cl/676517. func StaticValue(n Node) Node { for { switch n1 := n.(type) { diff --git a/src/cmd/compile/internal/ir/node_gen.go b/src/cmd/compile/internal/ir/node_gen.go index 026acbf9dd61f5..e67b5ba0bc16f0 100644 --- a/src/cmd/compile/internal/ir/node_gen.go +++ b/src/cmd/compile/internal/ir/node_gen.go @@ -2202,13 +2202,13 @@ func (n *TailCallStmt) doChildrenWithHidden(do func(Node) bool) bool { func (n *TailCallStmt) editChildren(edit func(Node) Node) { editNodes(n.init, edit) if n.Call != nil { - n.Call = edit(n.Call).(*CallExpr) + n.Call = edit(n.Call) } } func (n *TailCallStmt) editChildrenWithHidden(edit func(Node) Node) { editNodes(n.init, edit) if n.Call != nil { - n.Call = edit(n.Call).(*CallExpr) + n.Call = edit(n.Call) } } diff --git a/src/cmd/compile/internal/ir/stmt.go b/src/cmd/compile/internal/ir/stmt.go index 0801ecdd9e8722..ae7fb2080b6f3e 100644 --- a/src/cmd/compile/internal/ir/stmt.go +++ b/src/cmd/compile/internal/ir/stmt.go @@ -479,7 +479,7 @@ func NewSwitchStmt(pos src.XPos, tag Node, cases []*CaseClause) *SwitchStmt { // code generation to jump directly to another function entirely. type TailCallStmt struct { miniStmt - Call *CallExpr // the underlying call + Call Node // the underlying call } func NewTailCallStmt(pos src.XPos, call *CallExpr) *TailCallStmt { diff --git a/src/cmd/compile/internal/ir/symtab.go b/src/cmd/compile/internal/ir/symtab.go index e2da710f025878..820916316cbff8 100644 --- a/src/cmd/compile/internal/ir/symtab.go +++ b/src/cmd/compile/internal/ir/symtab.go @@ -59,13 +59,11 @@ type symsStruct struct { Udiv *obj.LSym WriteBarrier *obj.LSym Zerobase *obj.LSym - ZeroVal *obj.LSym ARM64HasATOMICS *obj.LSym ARMHasVFPv4 *obj.LSym Loong64HasLAMCAS *obj.LSym Loong64HasLAM_BH *obj.LSym Loong64HasLSX *obj.LSym - RISCV64HasZbb *obj.LSym X86HasFMA *obj.LSym X86HasPOPCNT *obj.LSym X86HasSSE41 *obj.LSym diff --git a/src/cmd/compile/internal/liveness/plive.go b/src/cmd/compile/internal/liveness/plive.go index 5a2a22ee8f5c82..6c97858cf6efbb 100644 --- a/src/cmd/compile/internal/liveness/plive.go +++ b/src/cmd/compile/internal/liveness/plive.go @@ -1414,7 +1414,9 @@ func Compute(curfn *ir.Func, f *ssa.Func, stkptrsize int64, pp *objw.Progs, retL { cache := f.Cache.Liveness.(*livenessFuncCache) if cap(lv.be) < 2000 { // Threshold from ssa.Cache slices. - clear(lv.be) + for i := range lv.be { + lv.be[i] = blockEffects{} + } cache.be = lv.be } if len(lv.livenessMap.Vals) < 2000 { diff --git a/src/cmd/compile/internal/logopt/logopt_test.go b/src/cmd/compile/internal/logopt/logopt_test.go index 1edabf9fb7ff04..c7debd9897d09b 100644 --- a/src/cmd/compile/internal/logopt/logopt_test.go +++ b/src/cmd/compile/internal/logopt/logopt_test.go @@ -203,16 +203,16 @@ func s15a8(x *[15]int64) [15]int64 { // escape analysis explanation want(t, slogged, `{"range":{"start":{"line":7,"character":13},"end":{"line":7,"character":13}},"severity":3,"code":"leak","source":"go compiler","message":"parameter z leaks to ~r0 with derefs=0",`+ `"relatedInformation":[`+ - `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: flow: y ← z:"},`+ + `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: flow: y = z:"},`+ `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: from y := z (assign-pair)"},`+ - `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: flow: ~r0 ← y:"},`+ + `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: flow: ~r0 = y:"},`+ `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":4,"character":11},"end":{"line":4,"character":11}}},"message":"inlineLoc"},`+ `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: from y.b (dot of pointer)"},`+ `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":4,"character":11},"end":{"line":4,"character":11}}},"message":"inlineLoc"},`+ `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: from \u0026y.b (address-of)"},`+ `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":4,"character":9},"end":{"line":4,"character":9}}},"message":"inlineLoc"},`+ `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: from ~r0 = \u0026y.b (assign-pair)"},`+ - `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":3},"end":{"line":9,"character":3}}},"message":"escflow: flow: ~r0 ← ~r0:"},`+ + `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":3},"end":{"line":9,"character":3}}},"message":"escflow: flow: ~r0 = ~r0:"},`+ `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":3},"end":{"line":9,"character":3}}},"message":"escflow: from return ~r0 (return)"}]}`) }) } diff --git a/src/cmd/compile/internal/loong64/ssa.go b/src/cmd/compile/internal/loong64/ssa.go index a71a5c3e43bf3f..60516d6618bbb2 100644 --- a/src/cmd/compile/internal/loong64/ssa.go +++ b/src/cmd/compile/internal/loong64/ssa.go @@ -165,8 +165,6 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { ssa.OpLOONG64OR, ssa.OpLOONG64XOR, ssa.OpLOONG64NOR, - ssa.OpLOONG64ANDN, - ssa.OpLOONG64ORN, ssa.OpLOONG64SLL, ssa.OpLOONG64SLLV, ssa.OpLOONG64SRL, @@ -278,6 +276,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { ssa.OpLOONG64ANDconst, ssa.OpLOONG64ORconst, ssa.OpLOONG64XORconst, + ssa.OpLOONG64NORconst, ssa.OpLOONG64SLLconst, ssa.OpLOONG64SLLVconst, ssa.OpLOONG64SRLconst, @@ -294,23 +293,6 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p.Reg = v.Args[0].Reg() p.To.Type = obj.TYPE_REG p.To.Reg = v.Reg() - - case ssa.OpLOONG64NORconst: - // MOVV $const, Rtmp - // NOR Rtmp, Rarg0, Rout - p := s.Prog(loong64.AMOVV) - p.From.Type = obj.TYPE_CONST - p.From.Offset = v.AuxInt - p.To.Type = obj.TYPE_REG - p.To.Reg = loong64.REGTMP - - p2 := s.Prog(v.Op.Asm()) - p2.From.Type = obj.TYPE_REG - p2.From.Reg = loong64.REGTMP - p2.Reg = v.Args[0].Reg() - p2.To.Type = obj.TYPE_REG - p2.To.Reg = v.Reg() - case ssa.OpLOONG64MOVVconst: r := v.Reg() p := s.Prog(v.Op.Asm()) @@ -966,24 +948,6 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p.Reg = v.Args[0].Reg() p.To.Type = obj.TYPE_REG p.To.Reg = v.Reg() - - case ssa.OpLOONG64PRELD: - // PRELD (Rarg0), hint - p := s.Prog(v.Op.Asm()) - p.From.Type = obj.TYPE_MEM - p.From.Reg = v.Args[0].Reg() - p.AddRestSourceConst(v.AuxInt & 0x1f) - - case ssa.OpLOONG64PRELDX: - // PRELDX (Rarg0), $n, $hint - p := s.Prog(v.Op.Asm()) - p.From.Type = obj.TYPE_MEM - p.From.Reg = v.Args[0].Reg() - p.AddRestSourceArgs([]obj.Addr{ - {Type: obj.TYPE_CONST, Offset: int64((v.AuxInt >> 5) & 0x1fffffffff)}, - {Type: obj.TYPE_CONST, Offset: int64((v.AuxInt >> 0) & 0x1f)}, - }) - case ssa.OpClobber, ssa.OpClobberReg: // TODO: implement for clobberdead experiment. Nop is ok for now. default: diff --git a/src/cmd/compile/internal/loopvar/loopvar.go b/src/cmd/compile/internal/loopvar/loopvar.go index 5a4590d2998d0c..030fc04c1369d8 100644 --- a/src/cmd/compile/internal/loopvar/loopvar.go +++ b/src/cmd/compile/internal/loopvar/loopvar.go @@ -305,7 +305,6 @@ func ForCapture(fn *ir.Func) []VarAndLoop { as := ir.NewAssignStmt(x.Pos(), z, tz) as.Def = true as.SetTypecheck(1) - z.Defn = as preBody.Append(as) dclFixups[z] = as diff --git a/src/cmd/compile/internal/mips/ssa.go b/src/cmd/compile/internal/mips/ssa.go index 9762554829c295..4c7c8eafcda30d 100644 --- a/src/cmd/compile/internal/mips/ssa.go +++ b/src/cmd/compile/internal/mips/ssa.go @@ -804,9 +804,6 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p := s.Prog(obj.AGETCALLERPC) p.To.Type = obj.TYPE_REG p.To.Reg = v.Reg() - case ssa.OpMIPSLoweredPubBarrier: - // SYNC - s.Prog(v.Op.Asm()) case ssa.OpClobber, ssa.OpClobberReg: // TODO: implement for clobberdead experiment. Nop is ok for now. default: diff --git a/src/cmd/compile/internal/mips64/ssa.go b/src/cmd/compile/internal/mips64/ssa.go index af94c16f6df592..5b5edf622a1e9b 100644 --- a/src/cmd/compile/internal/mips64/ssa.go +++ b/src/cmd/compile/internal/mips64/ssa.go @@ -813,9 +813,6 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { p := s.Prog(obj.AGETCALLERPC) p.To.Type = obj.TYPE_REG p.To.Reg = v.Reg() - case ssa.OpMIPS64LoweredPubBarrier: - // SYNC - s.Prog(v.Op.Asm()) case ssa.OpClobber, ssa.OpClobberReg: // TODO: implement for clobberdead experiment. Nop is ok for now. default: diff --git a/src/cmd/compile/internal/noder/doc.go b/src/cmd/compile/internal/noder/doc.go deleted file mode 100644 index a5d5533168c155..00000000000000 --- a/src/cmd/compile/internal/noder/doc.go +++ /dev/null @@ -1,273 +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. - -/* -The Unified IR (UIR) format is implicitly defined by the package noder. - -At the highest level, a package encoded in UIR follows the grammar -below. - - File = Header Payload fingerprint . - Header = version [ flags ] sectionEnds elementEnds . - - version = uint32 . // used for backward compatibility - flags = uint32 . // feature flags used across versions - sectionEnds = [10]uint32 . // defines section boundaries - elementEnds = []uint32 . // defines element boundaries - fingerprint = [8]byte . // sha256 fingerprint - -The payload is a series of sections. Each section has a kind which -determines its index in the series. - - SectionKind = Uint64 . - Payload = SectionString - SectionMeta - SectionPosBase - SectionPkg - SectionName - SectionType - SectionObj - SectionObjExt // TODO(markfreeman) Define. - SectionObjDict // TODO(markfreeman) Define. - SectionBody // TODO(markfreeman) Define. - . - -# Sections -A section is a series of elements of a type determined by the section's -kind. Go constructs are mapped onto one or more elements with possibly -different types; in that case, the elements are in different sections. - -Elements are accessed using an element index relative to the start of -the section. - - RelElemIdx = Uint64 . - -## String Section -String values are stored as elements in the string section. Elements -outside the string section access string values by reference. - - SectionString = { String } . - -Note that despite being an element, a string does not begin with a -reference table. - -## Meta Section -The meta section provides fundamental information for a package. It -contains exactly two elements — a public root and a private root. - - SectionMeta = PublicRoot - PrivateRoot // TODO(markfreeman): Define. - . - -The public root element identifies the package and provides references -for all exported objects it contains. - - PublicRoot = RefTable - [ Sync ] - PkgRef - [ HasInit ] - ObjectRefCount // TODO(markfreeman): Define. - { ObjectRef } // TODO(markfreeman): Define. - . - HasInit = Bool . // Whether the package uses any - // initialization functions. - -## PosBase Section -This section provides position information. It is a series of PosBase -elements. - - SectionPosBase = { PosBase } . - -A base is either a file base or line base (produced by a line -directive). Every base has a position, line, and column; these are -constant for file bases and hence not encoded. - - PosBase = RefTable - [ Sync ] - StringRef // the (absolute) file name for the base - Bool // true if a file base, else a line base - // The below is ommitted for file bases. - [ Pos - Uint64 // line - Uint64 ] // column - . - -A source position Pos represents a file-absolute (line, column) pair -and a PosBase indicating the position Pos is relative to. Positions -without a PosBase have no line or column. - - Pos = [ Sync ] - Bool // true if the position has a base - // The below is ommitted if the position has no base. - [ Ref[PosBase] - Uint64 // line - Uint64 ] // column - . - -## Package Section -The package section holds package information. It is a series of Pkg -elements. - - SectionPkg = { Pkg } . - -A Pkg element contains a (path, name) pair and a series of imported -packages. The below package paths have special meaning. - - +--------------+-----------------------------------+ - | package path | indicates | - +--------------+-----------------------------------+ - | "" | the current package | - | "builtin" | the fake builtin package | - | "unsafe" | the compiler-known unsafe package | - +--------------+-----------------------------------+ - - Pkg = RefTable - [ Sync ] - StringRef // path - // The below is ommitted for the special package paths - // "builtin" and "unsafe". - [ StringRef // name - Imports ] - . - Imports = Uint64 // the number of declared imports - { PkgRef } // references to declared imports - . - -Note, a PkgRef is *not* equivalent to Ref[Pkg] due to an extra marker. - - PkgRef = [ Sync ] - Ref[Pkg] - . - -## Type Section -The type section is a series of type definition elements. - - SectionType = { TypeDef } . - -A type definition can be in one of several formats, which are identified -by their TypeSpec code. - - TypeDef = RefTable - [ Sync ] - [ Sync ] - Uint64 // denotes which TypeSpec to use - TypeSpec - . - - TypeSpec = TypeSpecBasic // TODO(markfreeman): Define. - | TypeSpecNamed // TODO(markfreeman): Define. - | TypeSpecPointer // TODO(markfreeman): Define. - | TypeSpecSlice // TODO(markfreeman): Define. - | TypeSpecArray // TODO(markfreeman): Define. - | TypeSpecChan // TODO(markfreeman): Define. - | TypeSpecMap // TODO(markfreeman): Define. - | TypeSpecSignature // TODO(markfreeman): Define. - | TypeSpecStruct // TODO(markfreeman): Define. - | TypeSpecInterface // TODO(markfreeman): Define. - | TypeSpecUnion // TODO(markfreeman): Define. - | TypeSpecTypeParam // TODO(markfreeman): Define. - . - -// TODO(markfreeman): Document the reader dictionary once we understand it more. -To use a type elsewhere, a TypeUse is encoded. - - TypeUse = [ Sync ] - Bool // whether it is a derived type - [ Uint64 ] // if derived, an index into the reader dictionary - [ Ref[TypeDef] ] // else, a reference to the type - . - -## Object Sections -Information about an object (e.g. variable, function, type name, etc.) -is split into multiple elements in different sections. Those elements -have the same section-relative element index. - -### Name Section -The name section holds a series of names. - - SectionName = { Name } . - -Names are elements holding qualified identifiers and type information -for objects. - - Name = RefTable - [ Sync ] - [ Sync ] - PkgRef // the object's package - StringRef // the object's package-local name - [ Sync ] - Uint64 // the object's type (e.g. Var, Func, etc.) - . - -### Definition Section -The definition section holds definitions for objects defined by the target -package; it does not contain definitions for imported objects. - - SectionObj = { ObjectDef } . - -Object definitions can be in one of several formats. To determine the correct -format, the name section must be referenced; it contains a code indicating -the object's type. - - ObjectDef = RefTable - [ Sync ] - ObjectSpec - . - - ObjectSpec = ObjectSpecConst // TODO(markfreeman) Define. - | ObjectSpecFunc // TODO(markfreeman) Define. - | ObjectSpecAlias // TODO(markfreeman) Define. - | ObjectSpecNamedType // TODO(markfreeman) Define. - | ObjectSpecVar // TODO(markfreeman) Define. - . - -To use an object definition elsewhere, an ObjectUse is encoded. - - ObjectUse = [ Sync ] - [ Bool ] - Ref[ObjectDef] - Uint64 // the number of type arguments - { TypeUse } // references to the type arguments - . - -# References -A reference table precedes every element. Each entry in the table -contains a (section, index) pair denoting the location of the -referenced element. - - RefTable = [ Sync ] - Uint64 // the number of table entries - { RefTableEntry } - . - RefTableEntry = [ Sync ] - SectionKind - RelElemIdx - . - -Elements encode references to other elements as an index in the -reference table — not the location of the referenced element directly. - - RefTableIdx = Uint64 . - -To do this, the Ref[T] primitive is used as below; note that this is -the same shape as provided by package pkgbits, just with new -interpretation applied. - - Ref[T] = [ Sync ] - RefTableIdx // the Uint64 - . - -# Primitives -Primitive encoding is handled separately by the pkgbits package. Check -there for definitions of the below productions. - - * Bool - * Int64 - * Uint64 - * String - * Ref[T] - * Sync -*/ - -package noder diff --git a/src/cmd/compile/internal/noder/linker.go b/src/cmd/compile/internal/noder/linker.go index 51b03a1897e830..4f1cc7b612ecd2 100644 --- a/src/cmd/compile/internal/noder/linker.go +++ b/src/cmd/compile/internal/noder/linker.go @@ -47,8 +47,8 @@ type linker struct { // relocAll ensures that all elements specified by pr and relocs are // copied into the output export data file, and returns the // corresponding indices in the output. -func (l *linker) relocAll(pr *pkgReader, relocs []pkgbits.RefTableEntry) []pkgbits.RefTableEntry { - res := make([]pkgbits.RefTableEntry, len(relocs)) +func (l *linker) relocAll(pr *pkgReader, relocs []pkgbits.RelocEnt) []pkgbits.RelocEnt { + res := make([]pkgbits.RelocEnt, len(relocs)) for i, rent := range relocs { rent.Idx = l.relocIdx(pr, rent.Kind, rent.Idx) res[i] = rent @@ -58,7 +58,7 @@ func (l *linker) relocAll(pr *pkgReader, relocs []pkgbits.RefTableEntry) []pkgbi // relocIdx ensures a single element is copied into the output export // data file, and returns the corresponding index in the output. -func (l *linker) relocIdx(pr *pkgReader, k pkgbits.SectionKind, idx index) index { +func (l *linker) relocIdx(pr *pkgReader, k pkgbits.RelocKind, idx index) index { assert(pr != nil) absIdx := pr.AbsIdx(k, idx) @@ -69,11 +69,11 @@ func (l *linker) relocIdx(pr *pkgReader, k pkgbits.SectionKind, idx index) index var newidx index switch k { - case pkgbits.SectionString: + case pkgbits.RelocString: newidx = l.relocString(pr, idx) - case pkgbits.SectionPkg: + case pkgbits.RelocPkg: newidx = l.relocPkg(pr, idx) - case pkgbits.SectionObj: + case pkgbits.RelocObj: newidx = l.relocObj(pr, idx) default: @@ -84,7 +84,7 @@ func (l *linker) relocIdx(pr *pkgReader, k pkgbits.SectionKind, idx index) index // if we do external relocations. w := l.pw.NewEncoderRaw(k) - l.relocCommon(pr, w, k, idx) + l.relocCommon(pr, &w, k, idx) newidx = w.Idx } @@ -113,8 +113,8 @@ func (l *linker) relocPkg(pr *pkgReader, idx index) index { return newidx } - r := pr.NewDecoder(pkgbits.SectionPkg, idx, pkgbits.SyncPkgDef) - w := l.pw.NewEncoder(pkgbits.SectionPkg, pkgbits.SyncPkgDef) + r := pr.NewDecoder(pkgbits.RelocPkg, idx, pkgbits.SyncPkgDef) + w := l.pw.NewEncoder(pkgbits.RelocPkg, pkgbits.SyncPkgDef) l.pkgs[path] = w.Idx // TODO(mdempsky): We end up leaving an empty string reference here @@ -158,19 +158,19 @@ func (l *linker) relocObj(pr *pkgReader, idx index) index { assert(tag2 != pkgbits.ObjStub) } - w := l.pw.NewEncoderRaw(pkgbits.SectionObj) - wext := l.pw.NewEncoderRaw(pkgbits.SectionObjExt) - wname := l.pw.NewEncoderRaw(pkgbits.SectionName) - wdict := l.pw.NewEncoderRaw(pkgbits.SectionObjDict) + w := l.pw.NewEncoderRaw(pkgbits.RelocObj) + wext := l.pw.NewEncoderRaw(pkgbits.RelocObjExt) + wname := l.pw.NewEncoderRaw(pkgbits.RelocName) + wdict := l.pw.NewEncoderRaw(pkgbits.RelocObjDict) l.decls[sym] = w.Idx assert(wext.Idx == w.Idx) assert(wname.Idx == w.Idx) assert(wdict.Idx == w.Idx) - l.relocCommon(pr, w, pkgbits.SectionObj, idx) - l.relocCommon(pr, wname, pkgbits.SectionName, idx) - l.relocCommon(pr, wdict, pkgbits.SectionObjDict, idx) + l.relocCommon(pr, &w, pkgbits.RelocObj, idx) + l.relocCommon(pr, &wname, pkgbits.RelocName, idx) + l.relocCommon(pr, &wdict, pkgbits.RelocObjDict, idx) // Generic types and functions won't have definitions, and imported // objects may not either. @@ -181,15 +181,15 @@ func (l *linker) relocObj(pr *pkgReader, idx index) index { wext.Sync(pkgbits.SyncObject1) switch tag { case pkgbits.ObjFunc: - l.relocFuncExt(wext, obj) + l.relocFuncExt(&wext, obj) case pkgbits.ObjType: - l.relocTypeExt(wext, obj) + l.relocTypeExt(&wext, obj) case pkgbits.ObjVar: - l.relocVarExt(wext, obj) + l.relocVarExt(&wext, obj) } wext.Flush() } else { - l.relocCommon(pr, wext, pkgbits.SectionObjExt, idx) + l.relocCommon(pr, &wext, pkgbits.RelocObjExt, idx) } // Check if we need to export the inline bodies for functions and @@ -247,12 +247,12 @@ func (l *linker) exportBody(obj *ir.Name, local bool) { pri, ok := bodyReaderFor(fn) assert(ok) - l.bodies[sym] = l.relocIdx(pri.pr, pkgbits.SectionBody, pri.idx) + l.bodies[sym] = l.relocIdx(pri.pr, pkgbits.RelocBody, pri.idx) } // relocCommon copies the specified element from pr into w, // recursively relocating any referenced elements as well. -func (l *linker) relocCommon(pr *pkgReader, w *pkgbits.Encoder, k pkgbits.SectionKind, idx index) { +func (l *linker) relocCommon(pr *pkgReader, w *pkgbits.Encoder, k pkgbits.RelocKind, idx index) { r := pr.NewDecoderRaw(k, idx) w.Relocs = l.relocAll(pr, r.Relocs) io.Copy(&w.Data, &r.Data) diff --git a/src/cmd/compile/internal/noder/noder.go b/src/cmd/compile/internal/noder/noder.go index 79a90783336030..77daf9eda59085 100644 --- a/src/cmd/compile/internal/noder/noder.go +++ b/src/cmd/compile/internal/noder/noder.go @@ -458,7 +458,7 @@ func Renameinit() *types.Sym { func checkEmbed(decl *syntax.VarDecl, haveEmbed, withinFunc bool) error { switch { case !haveEmbed: - return errors.New("go:embed requires import \"embed\" (or import _ \"embed\", if package is not used)") + return errors.New("go:embed only allowed in Go files that import \"embed\"") case len(decl.NameList) > 1: return errors.New("go:embed cannot apply to multiple vars") case decl.Values != nil: diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index 38b0bc1d8a4153..0f08bce10f01d4 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -49,18 +49,15 @@ type pkgReader struct { // but bitwise inverted so we can detect if we're missing the entry // or not. newindex []index - - // indicates whether the data is reading during reshaping. - reshaping bool } func newPkgReader(pr pkgbits.PkgDecoder) *pkgReader { return &pkgReader{ PkgDecoder: pr, - posBases: make([]*src.PosBase, pr.NumElems(pkgbits.SectionPosBase)), - pkgs: make([]*types.Pkg, pr.NumElems(pkgbits.SectionPkg)), - typs: make([]*types.Type, pr.NumElems(pkgbits.SectionType)), + posBases: make([]*src.PosBase, pr.NumElems(pkgbits.RelocPosBase)), + pkgs: make([]*types.Pkg, pr.NumElems(pkgbits.RelocPkg)), + typs: make([]*types.Type, pr.NumElems(pkgbits.RelocType)), newindex: make([]index, pr.TotalElems()), } @@ -77,7 +74,7 @@ type pkgReaderIndex struct { synthetic func(pos src.XPos, r *reader) } -func (pri pkgReaderIndex) asReader(k pkgbits.SectionKind, marker pkgbits.SyncMarker) *reader { +func (pri pkgReaderIndex) asReader(k pkgbits.RelocKind, marker pkgbits.SyncMarker) *reader { if pri.synthetic != nil { return &reader{synthetic: pri.synthetic} } @@ -88,7 +85,7 @@ func (pri pkgReaderIndex) asReader(k pkgbits.SectionKind, marker pkgbits.SyncMar return r } -func (pr *pkgReader) newReader(k pkgbits.SectionKind, idx index, marker pkgbits.SyncMarker) *reader { +func (pr *pkgReader) newReader(k pkgbits.RelocKind, idx index, marker pkgbits.SyncMarker) *reader { return &reader{ Decoder: pr.NewDecoder(k, idx, marker), p: pr, @@ -119,10 +116,6 @@ type reader struct { // find parameters/results. funarghack bool - // reshaping is used during reading exprReshape code, preventing - // the reader from shapifying the re-shaped type. - reshaping bool - // methodSym is the name of method's name, if reading a method. // It's nil if reading a normal function or closure body. methodSym *types.Sym @@ -262,7 +255,7 @@ func (r *reader) pos0() src.Pos { // posBase reads a position base from the bitstream. func (r *reader) posBase() *src.PosBase { - return r.inlPosBase(r.p.posBaseIdx(r.Reloc(pkgbits.SectionPosBase))) + return r.inlPosBase(r.p.posBaseIdx(r.Reloc(pkgbits.RelocPosBase))) } // posBaseIdx returns the specified position base, reading it first if @@ -272,7 +265,7 @@ func (pr *pkgReader) posBaseIdx(idx index) *src.PosBase { return b } - r := pr.newReader(pkgbits.SectionPosBase, idx, pkgbits.SyncPosBase) + r := pr.newReader(pkgbits.RelocPosBase, idx, pkgbits.SyncPosBase) var b *src.PosBase absFilename := r.String() @@ -343,7 +336,7 @@ func (r *reader) inlPos(xpos src.XPos) src.XPos { // pkg reads a package reference from the bitstream. func (r *reader) pkg() *types.Pkg { r.Sync(pkgbits.SyncPkg) - return r.p.pkgIdx(r.Reloc(pkgbits.SectionPkg)) + return r.p.pkgIdx(r.Reloc(pkgbits.RelocPkg)) } // pkgIdx returns the specified package from the export data, reading @@ -353,7 +346,7 @@ func (pr *pkgReader) pkgIdx(idx index) *types.Pkg { return pkg } - pkg := pr.newReader(pkgbits.SectionPkg, idx, pkgbits.SyncPkgDef).doPkg() + pkg := pr.newReader(pkgbits.RelocPkg, idx, pkgbits.SyncPkgDef).doPkg() pr.pkgs[idx] = pkg return pkg } @@ -400,7 +393,7 @@ func (r *reader) typInfo() typeInfo { if r.Bool() { return typeInfo{idx: index(r.Len()), derived: true} } - return typeInfo{idx: r.Reloc(pkgbits.SectionType), derived: false} + return typeInfo{idx: r.Reloc(pkgbits.RelocType), derived: false} } // typListIdx returns a list of the specified types, resolving derived @@ -430,7 +423,7 @@ func (pr *pkgReader) typIdx(info typeInfo, dict *readerDict, wrapped bool) *type return typ } - r := pr.newReader(pkgbits.SectionType, idx, pkgbits.SyncTypeIdx) + r := pr.newReader(pkgbits.RelocType, idx, pkgbits.SyncTypeIdx) r.dict = dict typ := r.doTyp() @@ -650,7 +643,7 @@ func (r *reader) objInfo() objInfo { if r.Version().Has(pkgbits.DerivedFuncInstance) { assert(!r.Bool()) } - idx := r.Reloc(pkgbits.SectionObj) + idx := r.Reloc(pkgbits.RelocObj) explicits := make([]typeInfo, r.Len()) for i := range explicits { @@ -692,7 +685,7 @@ func (pr *pkgReader) objIdx(idx index, implicits, explicits []*types.Type, shape // Other sources of internal failure (such as duplicate definitions) still fail // the build. func (pr *pkgReader) objIdxMayFail(idx index, implicits, explicits []*types.Type, shaped bool) (ir.Node, error) { - rname := pr.newReader(pkgbits.SectionName, idx, pkgbits.SyncObject1) + rname := pr.newReader(pkgbits.RelocName, idx, pkgbits.SyncObject1) _, sym := rname.qualifiedIdent() tag := pkgbits.CodeObj(rname.Code(pkgbits.SyncCodeObj)) @@ -721,8 +714,8 @@ func (pr *pkgReader) objIdxMayFail(idx index, implicits, explicits []*types.Type return sym.Def.(*ir.Name), nil } - r := pr.newReader(pkgbits.SectionObj, idx, pkgbits.SyncObject1) - rext := pr.newReader(pkgbits.SectionObjExt, idx, pkgbits.SyncObject1) + r := pr.newReader(pkgbits.RelocObj, idx, pkgbits.SyncObject1) + rext := pr.newReader(pkgbits.RelocObjExt, idx, pkgbits.SyncObject1) r.dict = dict rext.dict = dict @@ -769,7 +762,7 @@ func (pr *pkgReader) objIdxMayFail(idx index, implicits, explicits []*types.Type if hack { if sym.Def != nil { name = sym.Def.(*ir.Name) - assert(types.IdenticalStrict(name.Type(), typ)) + assert(name.Type() == typ) return name, nil } sym.Def = name @@ -966,7 +959,7 @@ func shapify(targ *types.Type, basic bool) *types.Type { // objDictIdx reads and returns the specified object dictionary. func (pr *pkgReader) objDictIdx(sym *types.Sym, idx index, implicits, explicits []*types.Type, shaped bool) (*readerDict, error) { - r := pr.newReader(pkgbits.SectionObjDict, idx, pkgbits.SyncObject1) + r := pr.newReader(pkgbits.RelocObjDict, idx, pkgbits.SyncObject1) dict := readerDict{ shaped: shaped, @@ -991,7 +984,7 @@ func (pr *pkgReader) objDictIdx(sym *types.Sym, idx index, implicits, explicits dict.derived = make([]derivedInfo, r.Len()) dict.derivedTypes = make([]*types.Type, len(dict.derived)) for i := range dict.derived { - dict.derived[i] = derivedInfo{idx: r.Reloc(pkgbits.SectionType)} + dict.derived[i] = derivedInfo{idx: r.Reloc(pkgbits.RelocType)} if r.Version().Has(pkgbits.DerivedInfoNeeded) { assert(!r.Bool()) } @@ -1014,25 +1007,7 @@ func (pr *pkgReader) objDictIdx(sym *types.Sym, idx index, implicits, explicits // arguments. for i, targ := range dict.targs { basic := r.Bool() - isPointerShape := basic && targ.IsPtr() && !targ.Elem().NotInHeap() - // We should not do shapify during the reshaping process, see #71184. - // However, this only matters for shapify a pointer type, which will - // lose the original underlying type. - // - // Example with a pointer type: - // - // - First, shapifying *[]T -> *uint8 - // - During the reshaping process, *uint8 is shapified to *go.shape.uint8 - // - This ends up with a different type with the original *[]T - // - // For a non-pointer type: - // - // - int -> go.shape.int - // - go.shape.int -> go.shape.int - // - // We always end up with the identical type. - canShapify := !pr.reshaping || !isPointerShape - if dict.shaped && canShapify { + if dict.shaped { dict.targs[i] = shapify(targ, basic) } } @@ -1303,7 +1278,7 @@ func (r *reader) addBody(fn *ir.Func, method *types.Sym) { // generic functions; see comment in funcExt. assert(fn.Nname.Defn != nil) - idx := r.Reloc(pkgbits.SectionBody) + idx := r.Reloc(pkgbits.RelocBody) pri := pkgReaderIndex{r.p, idx, r.dict, method, nil} bodyReader[fn] = pri @@ -1317,7 +1292,7 @@ func (r *reader) addBody(fn *ir.Func, method *types.Sym) { } func (pri pkgReaderIndex) funcBody(fn *ir.Func) { - r := pri.asReader(pkgbits.SectionBody, pkgbits.SyncFuncBody) + r := pri.asReader(pkgbits.RelocBody, pkgbits.SyncFuncBody) r.funcBody(fn) } @@ -2470,10 +2445,7 @@ func (r *reader) expr() (res ir.Node) { case exprReshape: typ := r.typ() - old := r.reshaping - r.reshaping = true x := r.expr() - r.reshaping = old if types.IdenticalStrict(x.Type(), typ) { return x @@ -2596,10 +2568,7 @@ func (r *reader) funcInst(pos src.XPos) (wrapperFn, baseFn, dictPtr ir.Node) { info := r.dict.subdicts[idx] explicits := r.p.typListIdx(info.explicits, r.dict) - old := r.p.reshaping - r.p.reshaping = r.reshaping baseFn = r.p.objIdx(info.idx, implicits, explicits, true).(*ir.Name) - r.p.reshaping = old // TODO(mdempsky): Is there a more robust way to get the // dictionary pointer type here? @@ -2622,7 +2591,7 @@ func (r *reader) funcInst(pos src.XPos) (wrapperFn, baseFn, dictPtr ir.Node) { } func (pr *pkgReader) objDictName(idx index, implicits, explicits []*types.Type) *ir.Name { - rname := pr.newReader(pkgbits.SectionName, idx, pkgbits.SyncObject1) + rname := pr.newReader(pkgbits.RelocName, idx, pkgbits.SyncObject1) _, sym := rname.qualifiedIdent() tag := pkgbits.CodeObj(rname.Code(pkgbits.SyncCodeObj)) @@ -3468,7 +3437,7 @@ func unifiedInlineCall(callerfn *ir.Func, call *ir.CallExpr, fn *ir.Func, inlInd expandInline(fn, pri) } - r := pri.asReader(pkgbits.SectionBody, pkgbits.SyncFuncBody) + r := pri.asReader(pkgbits.RelocBody, pkgbits.SyncFuncBody) tmpfn := ir.NewFunc(fn.Pos(), fn.Nname.Pos(), callerfn.Sym(), fn.Type()) @@ -3657,7 +3626,7 @@ func expandInline(fn *ir.Func, pri pkgReaderIndex) { tmpfn.ClosureVars = fn.ClosureVars { - r := pri.asReader(pkgbits.SectionBody, pkgbits.SyncFuncBody) + r := pri.asReader(pkgbits.RelocBody, pkgbits.SyncFuncBody) // Don't change parameter's Sym/Nname fields. r.funarghack = true @@ -4014,12 +3983,11 @@ func addTailCall(pos src.XPos, fn *ir.Func, recv ir.Node, method *types.Field) { if recv.Type() != nil && recv.Type().IsPtr() && method.Type.Recv().Type.IsPtr() && method.Embedded != 0 && !types.IsInterfaceMethod(method.Type) && - !unifiedHaveInlineBody(ir.MethodExprName(dot).Func) && !(base.Ctxt.Arch.Name == "ppc64le" && base.Ctxt.Flag_dynlink) { if base.Debug.TailCall != 0 { base.WarnfAt(fn.Nname.Type().Recv().Type.Elem().Pos(), "tail call emitted for the method %v wrapper", method.Nname) } - // Prefer OTAILCALL to reduce code size (except the case when the called method can be inlined). + // Prefer OTAILCALL to reduce code size (the called method can be inlined). fn.Body.Append(ir.NewTailCallStmt(pos, call)) return } diff --git a/src/cmd/compile/internal/noder/unified.go b/src/cmd/compile/internal/noder/unified.go index 85982d7c189e14..59e8c1013fd168 100644 --- a/src/cmd/compile/internal/noder/unified.go +++ b/src/cmd/compile/internal/noder/unified.go @@ -199,7 +199,7 @@ func unified(m posMap, noders []*noder) { localPkgReader = newPkgReader(pkgbits.NewPkgDecoder(types.LocalPkg.Path, data)) readPackage(localPkgReader, types.LocalPkg, true) - r := localPkgReader.newReader(pkgbits.SectionMeta, pkgbits.PrivateRootIdx, pkgbits.SyncPrivate) + r := localPkgReader.newReader(pkgbits.RelocMeta, pkgbits.PrivateRootIdx, pkgbits.SyncPrivate) r.pkgInit(types.LocalPkg, target) readBodies(target, false) @@ -322,8 +322,8 @@ func writePkgStub(m posMap, noders []*noder) string { pw.collectDecls(noders) - publicRootWriter := pw.newWriter(pkgbits.SectionMeta, pkgbits.SyncPublic) - privateRootWriter := pw.newWriter(pkgbits.SectionMeta, pkgbits.SyncPrivate) + publicRootWriter := pw.newWriter(pkgbits.RelocMeta, pkgbits.SyncPublic) + privateRootWriter := pw.newWriter(pkgbits.RelocMeta, pkgbits.SyncPrivate) assert(publicRootWriter.Idx == pkgbits.PublicRootIdx) assert(privateRootWriter.Idx == pkgbits.PrivateRootIdx) @@ -406,7 +406,7 @@ func freePackage(pkg *types2.Package) { // import. func readPackage(pr *pkgReader, importpkg *types.Pkg, localStub bool) { { - r := pr.newReader(pkgbits.SectionMeta, pkgbits.PublicRootIdx, pkgbits.SyncPublic) + r := pr.newReader(pkgbits.RelocMeta, pkgbits.PublicRootIdx, pkgbits.SyncPublic) pkg := r.pkg() // This error can happen if "go tool compile" is called with wrong "-p" flag, see issue #54542. @@ -424,7 +424,7 @@ func readPackage(pr *pkgReader, importpkg *types.Pkg, localStub bool) { if r.Version().Has(pkgbits.DerivedFuncInstance) { assert(!r.Bool()) } - idx := r.Reloc(pkgbits.SectionObj) + idx := r.Reloc(pkgbits.RelocObj) assert(r.Len() == 0) path, name, code := r.p.PeekObj(idx) @@ -437,7 +437,7 @@ func readPackage(pr *pkgReader, importpkg *types.Pkg, localStub bool) { } if !localStub { - r := pr.newReader(pkgbits.SectionMeta, pkgbits.PrivateRootIdx, pkgbits.SyncPrivate) + r := pr.newReader(pkgbits.RelocMeta, pkgbits.PrivateRootIdx, pkgbits.SyncPrivate) if r.Bool() { sym := importpkg.Lookup(".inittask") @@ -449,7 +449,7 @@ func readPackage(pr *pkgReader, importpkg *types.Pkg, localStub bool) { for i, n := 0, r.Len(); i < n; i++ { path := r.String() name := r.String() - idx := r.Reloc(pkgbits.SectionBody) + idx := r.Reloc(pkgbits.RelocBody) sym := types.NewPkg(path, "").Lookup(name) if _, ok := importBodyReader[sym]; !ok { @@ -477,8 +477,8 @@ func writeUnifiedExport(out io.Writer) { bodies: make(map[*types.Sym]index), } - publicRootWriter := l.pw.NewEncoder(pkgbits.SectionMeta, pkgbits.SyncPublic) - privateRootWriter := l.pw.NewEncoder(pkgbits.SectionMeta, pkgbits.SyncPrivate) + publicRootWriter := l.pw.NewEncoder(pkgbits.RelocMeta, pkgbits.SyncPublic) + privateRootWriter := l.pw.NewEncoder(pkgbits.RelocMeta, pkgbits.SyncPrivate) assert(publicRootWriter.Idx == pkgbits.PublicRootIdx) assert(privateRootWriter.Idx == pkgbits.PrivateRootIdx) @@ -486,10 +486,10 @@ func writeUnifiedExport(out io.Writer) { { pr := localPkgReader - r := pr.NewDecoder(pkgbits.SectionMeta, pkgbits.PublicRootIdx, pkgbits.SyncPublic) + r := pr.NewDecoder(pkgbits.RelocMeta, pkgbits.PublicRootIdx, pkgbits.SyncPublic) r.Sync(pkgbits.SyncPkg) - selfPkgIdx = l.relocIdx(pr, pkgbits.SectionPkg, r.Reloc(pkgbits.SectionPkg)) + selfPkgIdx = l.relocIdx(pr, pkgbits.RelocPkg, r.Reloc(pkgbits.RelocPkg)) if r.Version().Has(pkgbits.HasInit) { r.Bool() @@ -500,7 +500,7 @@ func writeUnifiedExport(out io.Writer) { if r.Version().Has(pkgbits.DerivedFuncInstance) { assert(!r.Bool()) } - idx := r.Reloc(pkgbits.SectionObj) + idx := r.Reloc(pkgbits.RelocObj) assert(r.Len() == 0) xpath, xname, xtag := pr.PeekObj(idx) @@ -508,7 +508,7 @@ func writeUnifiedExport(out io.Writer) { assert(xtag != pkgbits.ObjStub) if types.IsExported(xname) { - l.relocIdx(pr, pkgbits.SectionObj, idx) + l.relocIdx(pr, pkgbits.RelocObj, idx) } } @@ -525,7 +525,7 @@ func writeUnifiedExport(out io.Writer) { w := publicRootWriter w.Sync(pkgbits.SyncPkg) - w.Reloc(pkgbits.SectionPkg, selfPkgIdx) + w.Reloc(pkgbits.RelocPkg, selfPkgIdx) if w.Version().Has(pkgbits.HasInit) { w.Bool(false) @@ -537,7 +537,7 @@ func writeUnifiedExport(out io.Writer) { if w.Version().Has(pkgbits.DerivedFuncInstance) { w.Bool(false) } - w.Reloc(pkgbits.SectionObj, idx) + w.Reloc(pkgbits.RelocObj, idx) w.Len(0) } @@ -564,7 +564,7 @@ func writeUnifiedExport(out io.Writer) { for _, body := range bodies { w.String(body.sym.Pkg.Path) w.String(body.sym.Name) - w.Reloc(pkgbits.SectionBody, body.idx) + w.Reloc(pkgbits.RelocBody, body.idx) } w.Sync(pkgbits.SyncEOF) diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index dd79c3ef4c87cb..f4b02f279dd5f2 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -174,7 +174,7 @@ func (pw *pkgWriter) typeOf(expr syntax.Expr) types2.Type { type writer struct { p *pkgWriter - *pkgbits.Encoder + pkgbits.Encoder // sig holds the signature for the current function body, if any. sig *types2.Signature @@ -367,7 +367,7 @@ func (dict *writerDict) itabIdx(typInfo, ifaceInfo typeInfo) int { return idx } -func (pw *pkgWriter) newWriter(k pkgbits.SectionKind, marker pkgbits.SyncMarker) *writer { +func (pw *pkgWriter) newWriter(k pkgbits.RelocKind, marker pkgbits.SyncMarker) *writer { return &writer{ Encoder: pw.NewEncoder(k, marker), p: pw, @@ -395,7 +395,7 @@ func (w *writer) pos(p poser) { // posBase writes a reference to the given PosBase into the element // bitstream. func (w *writer) posBase(b *syntax.PosBase) { - w.Reloc(pkgbits.SectionPosBase, w.p.posBaseIdx(b)) + w.Reloc(pkgbits.RelocPosBase, w.p.posBaseIdx(b)) } // posBaseIdx returns the index for the given PosBase. @@ -404,7 +404,7 @@ func (pw *pkgWriter) posBaseIdx(b *syntax.PosBase) index { return idx } - w := pw.newWriter(pkgbits.SectionPosBase, pkgbits.SyncPosBase) + w := pw.newWriter(pkgbits.RelocPosBase, pkgbits.SyncPosBase) w.p.posBasesIdx[b] = w.Idx w.String(trimFilename(b)) @@ -427,7 +427,7 @@ func (w *writer) pkg(pkg *types2.Package) { func (w *writer) pkgRef(idx index) { w.Sync(pkgbits.SyncPkg) - w.Reloc(pkgbits.SectionPkg, idx) + w.Reloc(pkgbits.RelocPkg, idx) } // pkgIdx returns the index for the given package, adding it to the @@ -437,7 +437,7 @@ func (pw *pkgWriter) pkgIdx(pkg *types2.Package) index { return idx } - w := pw.newWriter(pkgbits.SectionPkg, pkgbits.SyncPkgDef) + w := pw.newWriter(pkgbits.RelocPkg, pkgbits.SyncPkgDef) pw.pkgsIdx[pkg] = w.Idx // The universe and package unsafe need to be handled specially by @@ -489,7 +489,7 @@ func (w *writer) typInfo(info typeInfo) { w.Len(int(info.idx)) w.derived = true } else { - w.Reloc(pkgbits.SectionType, info.idx) + w.Reloc(pkgbits.RelocType, info.idx) } } @@ -520,7 +520,7 @@ func (pw *pkgWriter) typIdx(typ types2.Type, dict *writerDict) typeInfo { } } - w := pw.newWriter(pkgbits.SectionType, pkgbits.SyncTypeIdx) + w := pw.newWriter(pkgbits.RelocType, pkgbits.SyncTypeIdx) w.dict = dict switch typ := typ.(type) { @@ -737,7 +737,7 @@ func (w *writer) objInfo(info objInfo) { if w.Version().Has(pkgbits.DerivedFuncInstance) { w.Bool(false) } - w.Reloc(pkgbits.SectionObj, info.idx) + w.Reloc(pkgbits.RelocObj, info.idx) w.Len(len(info.explicits)) for _, info := range info.explicits { @@ -799,10 +799,10 @@ func (pw *pkgWriter) objIdx(obj types2.Object) index { // TODO(mdempsky): Re-evaluate whether RelocName still makes sense // to keep separate from RelocObj. - w := pw.newWriter(pkgbits.SectionObj, pkgbits.SyncObject1) - wext := pw.newWriter(pkgbits.SectionObjExt, pkgbits.SyncObject1) - wname := pw.newWriter(pkgbits.SectionName, pkgbits.SyncObject1) - wdict := pw.newWriter(pkgbits.SectionObjDict, pkgbits.SyncObject1) + w := pw.newWriter(pkgbits.RelocObj, pkgbits.SyncObject1) + wext := pw.newWriter(pkgbits.RelocObjExt, pkgbits.SyncObject1) + wname := pw.newWriter(pkgbits.RelocName, pkgbits.SyncObject1) + wdict := pw.newWriter(pkgbits.RelocObjDict, pkgbits.SyncObject1) pw.objsIdx[obj] = w.Idx // break cycles assert(wext.Idx == w.Idx) @@ -917,7 +917,7 @@ func (w *writer) objDict(obj types2.Object, dict *writerDict) { nderived := len(dict.derived) w.Len(nderived) for _, typ := range dict.derived { - w.Reloc(pkgbits.SectionType, typ.idx) + w.Reloc(pkgbits.RelocType, typ.idx) if w.Version().Has(pkgbits.DerivedInfoNeeded) { w.Bool(false) } @@ -1132,7 +1132,7 @@ func (w *writer) funcExt(obj *types2.Func) { } w.Bool(false) // stub extension - w.Reloc(pkgbits.SectionBody, body) + w.Reloc(pkgbits.RelocBody, body) w.Sync(pkgbits.SyncEOF) } @@ -1170,7 +1170,7 @@ func (w *writer) pragmaFlag(p ir.PragmaFlag) { // bodyIdx returns the index for the given function body (specified by // block), adding it to the export data func (pw *pkgWriter) bodyIdx(sig *types2.Signature, block *syntax.BlockStmt, dict *writerDict) (idx index, closureVars []posVar) { - w := pw.newWriter(pkgbits.SectionBody, pkgbits.SyncFuncBody) + w := pw.newWriter(pkgbits.RelocBody, pkgbits.SyncFuncBody) w.sig = sig w.dict = dict @@ -2401,7 +2401,7 @@ func (w *writer) funcLit(expr *syntax.FuncLit) { w.useLocal(cv.pos, cv.var_) } - w.Reloc(pkgbits.SectionBody, body) + w.Reloc(pkgbits.RelocBody, body) } type posVar struct { diff --git a/src/cmd/compile/internal/objw/prog.go b/src/cmd/compile/internal/objw/prog.go index 753fd8615ca9c5..84fb9967235ea0 100644 --- a/src/cmd/compile/internal/objw/prog.go +++ b/src/cmd/compile/internal/objw/prog.go @@ -116,7 +116,10 @@ func (pp *Progs) Flush() { func (pp *Progs) Free() { if base.Ctxt.CanReuseProgs() { // Clear progs to enable GC and avoid abuse. - clear(pp.Cache[:pp.CacheIndex]) + s := pp.Cache[:pp.CacheIndex] + for i := range s { + s[i] = obj.Prog{} + } } // Clear pp to avoid abuse. *pp = Progs{} diff --git a/src/cmd/compile/internal/pkginit/initAsanGlobals.go b/src/cmd/compile/internal/pkginit/initAsanGlobals.go index 96c052204a2c11..42db0eaf1bbd2a 100644 --- a/src/cmd/compile/internal/pkginit/initAsanGlobals.go +++ b/src/cmd/compile/internal/pkginit/initAsanGlobals.go @@ -227,12 +227,6 @@ func canInstrumentGlobal(g ir.Node) bool { return false } - // Do not instrument counter globals in internal/fuzz. These globals are replaced by the linker. - // See go.dev/issue/72766 for more details. - if n.Sym().Pkg.Path == "internal/fuzz" && (n.Sym().Name == "_counters" || n.Sym().Name == "_ecounters") { - return false - } - // Do not instrument globals that are linknamed, because their home package will do the work. if n.Sym().Linkname != "" { return false diff --git a/src/cmd/compile/internal/reflectdata/map_swiss.go b/src/cmd/compile/internal/reflectdata/map_swiss.go index 54266a604a7ec2..074c36a453339a 100644 --- a/src/cmd/compile/internal/reflectdata/map_swiss.go +++ b/src/cmd/compile/internal/reflectdata/map_swiss.go @@ -159,7 +159,6 @@ func SwissMapType() *types.Type { // globalShift uint8 // // writing uint8 - // tombstonePossible bool // // N.B Padding // // clearSeq uint64 @@ -173,7 +172,6 @@ func SwissMapType() *types.Type { makefield("globalDepth", types.Types[types.TUINT8]), makefield("globalShift", types.Types[types.TUINT8]), makefield("writing", types.Types[types.TUINT8]), - makefield("tombstonePossible", types.Types[types.TBOOL]), makefield("clearSeq", types.Types[types.TUINT64]), } diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index fb60569670ea66..4202ff3358f51d 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -1284,7 +1284,9 @@ func dgcptrmask(t *types.Type, write bool) *obj.LSym { // word offsets in t that hold pointers. // ptrmask is assumed to fit at least types.PtrDataSize(t)/PtrSize bits. func fillptrmask(t *types.Type, ptrmask []byte) { - clear(ptrmask) + for i := range ptrmask { + ptrmask[i] = 0 + } if !t.HasPointers() { return } diff --git a/src/cmd/compile/internal/riscv64/ssa.go b/src/cmd/compile/internal/riscv64/ssa.go index 21edcabc58b3a8..952a2050a08e08 100644 --- a/src/cmd/compile/internal/riscv64/ssa.go +++ b/src/cmd/compile/internal/riscv64/ssa.go @@ -419,8 +419,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { ssa.OpRISCV64FMVSX, ssa.OpRISCV64FMVDX, ssa.OpRISCV64FCVTSW, ssa.OpRISCV64FCVTSL, ssa.OpRISCV64FCVTWS, ssa.OpRISCV64FCVTLS, ssa.OpRISCV64FCVTDW, ssa.OpRISCV64FCVTDL, ssa.OpRISCV64FCVTWD, ssa.OpRISCV64FCVTLD, ssa.OpRISCV64FCVTDS, ssa.OpRISCV64FCVTSD, - ssa.OpRISCV64NOT, ssa.OpRISCV64NEG, ssa.OpRISCV64NEGW, ssa.OpRISCV64CLZ, ssa.OpRISCV64CLZW, ssa.OpRISCV64CTZ, ssa.OpRISCV64CTZW, - ssa.OpRISCV64REV8, ssa.OpRISCV64CPOP, ssa.OpRISCV64CPOPW: + ssa.OpRISCV64NOT, ssa.OpRISCV64NEG, ssa.OpRISCV64NEGW, ssa.OpRISCV64CLZ, ssa.OpRISCV64CLZW, ssa.OpRISCV64CTZ, ssa.OpRISCV64CTZW: p := s.Prog(v.Op.Asm()) p.From.Type = obj.TYPE_REG p.From.Reg = v.Args[0].Reg() diff --git a/src/cmd/compile/internal/ssa/_gen/AMD64.rules b/src/cmd/compile/internal/ssa/_gen/AMD64.rules index d55dfe70acc155..dd3b9a68d744c7 100644 --- a/src/cmd/compile/internal/ssa/_gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/_gen/AMD64.rules @@ -882,10 +882,44 @@ // (ANDQconst [0xFFFFFFFF] x) => (MOVLQZX x) // strength reduction +// Assumes that the following costs from https://gmplib.org/~tege/x86-timing.pdf: +// 1 - addq, shlq, leaq, negq, subq +// 3 - imulq +// This limits the rewrites to two instructions. +// Note that negq always operates in-place, +// which can require a register-register move +// to preserve the original value, +// so it must be used with care. +(MUL(Q|L)const [-9] x) => (NEG(Q|L) (LEA(Q|L)8x x)) +(MUL(Q|L)const [-5] x) => (NEG(Q|L) (LEA(Q|L)4 x x)) +(MUL(Q|L)const [-3] x) => (NEG(Q|L) (LEA(Q|L)2 x x)) +(MUL(Q|L)const [-1] x) => (NEG(Q|L) x) (MUL(Q|L)const [ 0] _) => (MOV(Q|L)const [0]) (MUL(Q|L)const [ 1] x) => x -(MULQconst [c] x) && canMulStrengthReduce(config, int64(c)) => {mulStrengthReduce(v, x, int64(c))} -(MULLconst [c] x) && v.Type.Size() <= 4 && canMulStrengthReduce32(config, c) => {mulStrengthReduce32(v, x, c)} +(MUL(Q|L)const [ 3] x) => (LEA(Q|L)2 x x) +(MUL(Q|L)const [ 5] x) => (LEA(Q|L)4 x x) +(MUL(Q|L)const [ 7] x) => (LEA(Q|L)2 x (LEA(Q|L)2 x x)) +(MUL(Q|L)const [ 9] x) => (LEA(Q|L)8 x x) +(MUL(Q|L)const [11] x) => (LEA(Q|L)2 x (LEA(Q|L)4 x x)) +(MUL(Q|L)const [13] x) => (LEA(Q|L)4 x (LEA(Q|L)2 x x)) +(MUL(Q|L)const [19] x) => (LEA(Q|L)2 x (LEA(Q|L)8 x x)) +(MUL(Q|L)const [21] x) => (LEA(Q|L)4 x (LEA(Q|L)4 x x)) +(MUL(Q|L)const [25] x) => (LEA(Q|L)8 x (LEA(Q|L)2 x x)) +(MUL(Q|L)const [27] x) => (LEA(Q|L)8 (LEA(Q|L)2 x x) (LEA(Q|L)2 x x)) +(MUL(Q|L)const [37] x) => (LEA(Q|L)4 x (LEA(Q|L)8 x x)) +(MUL(Q|L)const [41] x) => (LEA(Q|L)8 x (LEA(Q|L)4 x x)) +(MUL(Q|L)const [45] x) => (LEA(Q|L)8 (LEA(Q|L)4 x x) (LEA(Q|L)4 x x)) +(MUL(Q|L)const [73] x) => (LEA(Q|L)8 x (LEA(Q|L)8 x x)) +(MUL(Q|L)const [81] x) => (LEA(Q|L)8 (LEA(Q|L)8 x x) (LEA(Q|L)8 x x)) + +(MUL(Q|L)const [c] x) && isPowerOfTwo(int64(c)+1) && c >= 15 => (SUB(Q|L) (SHL(Q|L)const [int8(log64(int64(c)+1))] x) x) +(MUL(Q|L)const [c] x) && isPowerOfTwo(c-1) && c >= 17 => (LEA(Q|L)1 (SHL(Q|L)const [int8(log32(c-1))] x) x) +(MUL(Q|L)const [c] x) && isPowerOfTwo(c-2) && c >= 34 => (LEA(Q|L)2 (SHL(Q|L)const [int8(log32(c-2))] x) x) +(MUL(Q|L)const [c] x) && isPowerOfTwo(c-4) && c >= 68 => (LEA(Q|L)4 (SHL(Q|L)const [int8(log32(c-4))] x) x) +(MUL(Q|L)const [c] x) && isPowerOfTwo(c-8) && c >= 136 => (LEA(Q|L)8 (SHL(Q|L)const [int8(log32(c-8))] x) x) +(MUL(Q|L)const [c] x) && c%3 == 0 && isPowerOfTwo(c/3) => (SHL(Q|L)const [int8(log32(c/3))] (LEA(Q|L)2 x x)) +(MUL(Q|L)const [c] x) && c%5 == 0 && isPowerOfTwo(c/5) => (SHL(Q|L)const [int8(log32(c/5))] (LEA(Q|L)4 x x)) +(MUL(Q|L)const [c] x) && c%9 == 0 && isPowerOfTwo(c/9) => (SHL(Q|L)const [int8(log32(c/9))] (LEA(Q|L)8 x x)) // Prefer addition when shifting left by one (SHL(Q|L)const [1] x) => (ADD(Q|L) x x) @@ -921,12 +955,12 @@ (LEA(Q|L)8 [c] {s} x (ADD(Q|L)const [d] y)) && is32Bit(int64(c)+8*int64(d)) && y.Op != OpSB => (LEA(Q|L)8 [c+8*d] {s} x y) // fold shifts into LEAQx/LEALx -(LEA(Q|L)1 [c] {s} x z:(ADD(Q|L) y y)) && x != z => (LEA(Q|L)2 [c] {s} x y) +(LEA(Q|L)1 [c] {s} x (ADD(Q|L) y y)) => (LEA(Q|L)2 [c] {s} x y) (LEA(Q|L)1 [c] {s} x (SHL(Q|L)const [2] y)) => (LEA(Q|L)4 [c] {s} x y) (LEA(Q|L)1 [c] {s} x (SHL(Q|L)const [3] y)) => (LEA(Q|L)8 [c] {s} x y) -(LEA(Q|L)2 [c] {s} x z:(ADD(Q|L) y y)) && x != z => (LEA(Q|L)4 [c] {s} x y) +(LEA(Q|L)2 [c] {s} x (ADD(Q|L) y y)) => (LEA(Q|L)4 [c] {s} x y) (LEA(Q|L)2 [c] {s} x (SHL(Q|L)const [2] y)) => (LEA(Q|L)8 [c] {s} x y) -(LEA(Q|L)4 [c] {s} x z:(ADD(Q|L) y y)) && x != z => (LEA(Q|L)8 [c] {s} x y) +(LEA(Q|L)4 [c] {s} x (ADD(Q|L) y y)) => (LEA(Q|L)8 [c] {s} x y) // (x + x) << 1 -> x << 2 (LEA(Q|L)2 [0] {s} (ADD(Q|L) x x) x) && s == nil => (SHL(Q|L)const [2] x) @@ -1670,13 +1704,3 @@ // Convert atomic logical operations to easier ones if we don't use the result. (Select1 a:(LoweredAtomic(And64|And32|Or64|Or32) ptr val mem)) && a.Uses == 1 && clobber(a) => ((ANDQ|ANDL|ORQ|ORL)lock ptr val mem) - -// If we are checking the results of an add, use the flags directly from the add. -// Note that this only works for EQ/NE. ADD sets the CF/OF flags differently -// than TEST sets them. -// Note also that a.Args[0] here refers to the post-flagify'd value. -((EQ|NE) t:(TESTQ a:(ADDQconst [c] x) a)) && t.Uses == 1 && flagify(a) => ((EQ|NE) (Select1 a.Args[0])) -((EQ|NE) t:(TESTL a:(ADDLconst [c] x) a)) && t.Uses == 1 && flagify(a) => ((EQ|NE) (Select1 a.Args[0])) - -// If we don't use the flags any more, just use the standard op. -(Select0 a:(ADD(Q|L)constflags [c] x)) && a.Uses == 1 => (ADD(Q|L)const [c] x) diff --git a/src/cmd/compile/internal/ssa/_gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/_gen/AMD64Ops.go index 0f17843565276a..1cce32eba32523 100644 --- a/src/cmd/compile/internal/ssa/_gen/AMD64Ops.go +++ b/src/cmd/compile/internal/ssa/_gen/AMD64Ops.go @@ -303,11 +303,6 @@ func init() { // computes -arg0, flags set for 0-arg0. {name: "NEGLflags", argLength: 1, reg: gp11flags, typ: "(UInt32,Flags)", asm: "NEGL", resultInArg0: true}, - // compute arg0+auxint. flags set for arg0+auxint. - // NOTE: we pretend the CF/OF flags are undefined for these instructions, - // so we can use INC/DEC instead of ADDQconst if auxint is +/-1. (INC/DEC don't modify CF.) - {name: "ADDQconstflags", argLength: 1, reg: gp11flags, aux: "Int32", asm: "ADDQ", resultInArg0: true}, - {name: "ADDLconstflags", argLength: 1, reg: gp11flags, aux: "Int32", asm: "ADDL", resultInArg0: true}, // The following 4 add opcodes return the low 64 bits of the sum in the first result and // the carry (the 65th bit) in the carry flag. @@ -897,8 +892,8 @@ func init() { inputs: []regMask{buildReg("DI")}, clobbers: buildReg("DI"), }, - //faultOnNilArg0: true, // Note: removed for 73748. TODO: reenable at some point - unsafePoint: true, // FP maintenance around DUFFCOPY can be clobbered by interrupts + faultOnNilArg0: true, + unsafePoint: true, // FP maintenance around DUFFCOPY can be clobbered by interrupts }, // arg0 = address of memory to zero @@ -935,10 +930,10 @@ func init() { inputs: []regMask{buildReg("DI"), buildReg("SI")}, clobbers: buildReg("DI SI X0"), // uses X0 as a temporary }, - clobberFlags: true, - //faultOnNilArg0: true, // Note: removed for 73748. TODO: reenable at some point - //faultOnNilArg1: true, - unsafePoint: true, // FP maintenance around DUFFCOPY can be clobbered by interrupts + clobberFlags: true, + faultOnNilArg0: true, + faultOnNilArg1: true, + unsafePoint: true, // FP maintenance around DUFFCOPY can be clobbered by interrupts }, // arg0 = destination pointer diff --git a/src/cmd/compile/internal/ssa/_gen/ARM64.rules b/src/cmd/compile/internal/ssa/_gen/ARM64.rules index 01fe3a74f7d551..70400467111472 100644 --- a/src/cmd/compile/internal/ssa/_gen/ARM64.rules +++ b/src/cmd/compile/internal/ssa/_gen/ARM64.rules @@ -472,39 +472,26 @@ (MOVDstore dst (MOVDload src mem) mem)) (Move [16] dst src mem) => (STP dst (Select0 (LDP src mem)) (Select1 (LDP src mem)) mem) - -(Move [s] dst src mem) && s > 16 && s <= 24 => - (MOVDstore [int32(s-8)] dst (MOVDload [int32(s-8)] src mem) - (STP dst (Select0 (LDP src mem)) (Select1 (LDP src mem)) mem)) -(Move [s] dst src mem) && s > 24 && s <= 32 => - (STP [int32(s-16)] dst (Select0 (LDP [int32(s-16)] src mem)) (Select1 (LDP [int32(s-16)] src mem)) +(Move [32] dst src mem) => + (STP [16] dst (Select0 (LDP [16] src mem)) (Select1 (LDP [16] src mem)) (STP dst (Select0 (LDP src mem)) (Select1 (LDP src mem)) mem)) -(Move [s] dst src mem) && s > 32 && s <= 40 => - (MOVDstore [int32(s-8)] dst (MOVDload [int32(s-8)] src mem) +(Move [48] dst src mem) => + (STP [32] dst (Select0 (LDP [32] src mem)) (Select1 (LDP [32] src mem)) (STP [16] dst (Select0 (LDP [16] src mem)) (Select1 (LDP [16] src mem)) (STP dst (Select0 (LDP src mem)) (Select1 (LDP src mem)) mem))) -(Move [s] dst src mem) && s > 40 && s <= 48 => - (STP [int32(s-16)] dst (Select0 (LDP [int32(s-16)] src mem)) (Select1 (LDP [int32(s-16)] src mem)) - (STP [16] dst (Select0 (LDP [16] src mem)) (Select1 (LDP [16] src mem)) - (STP dst (Select0 (LDP src mem)) (Select1 (LDP src mem)) mem))) -(Move [s] dst src mem) && s > 48 && s <= 56 => - (MOVDstore [int32(s-8)] dst (MOVDload [int32(s-8)] src mem) - (STP [32] dst (Select0 (LDP [32] src mem)) (Select1 (LDP [32] src mem)) - (STP [16] dst (Select0 (LDP [16] src mem)) (Select1 (LDP [16] src mem)) - (STP dst (Select0 (LDP src mem)) (Select1 (LDP src mem)) mem)))) -(Move [s] dst src mem) && s > 56 && s <= 64 => - (STP [int32(s-16)] dst (Select0 (LDP [int32(s-16)] src mem)) (Select1 (LDP [int32(s-16)] src mem)) +(Move [64] dst src mem) => + (STP [48] dst (Select0 (LDP [48] src mem)) (Select1 (LDP [48] src mem)) (STP [32] dst (Select0 (LDP [32] src mem)) (Select1 (LDP [32] src mem)) (STP [16] dst (Select0 (LDP [16] src mem)) (Select1 (LDP [16] src mem)) (STP dst (Select0 (LDP src mem)) (Select1 (LDP src mem)) mem)))) // strip off fractional word move -(Move [s] dst src mem) && s%16 != 0 && s%16 <= 8 && s > 64 => +(Move [s] dst src mem) && s%16 != 0 && s%16 <= 8 && s > 16 => (Move [8] (OffPtr dst [s-8]) (OffPtr src [s-8]) (Move [s-s%16] dst src mem)) -(Move [s] dst src mem) && s%16 != 0 && s%16 > 8 && s > 64 => +(Move [s] dst src mem) && s%16 != 0 && s%16 > 8 && s > 16 => (Move [16] (OffPtr dst [s-16]) (OffPtr src [s-16]) @@ -1064,14 +1051,27 @@ (SBCSflags x y (Select1 (NEGSflags (MOVDconst [0])))) => (SUBSflags x y) // mul by constant +(MUL x (MOVDconst [-1])) => (NEG x) (MUL _ (MOVDconst [0])) => (MOVDconst [0]) (MUL x (MOVDconst [1])) => x - +(MUL x (MOVDconst [c])) && isPowerOfTwo(c) => (SLLconst [log64(c)] x) +(MUL x (MOVDconst [c])) && isPowerOfTwo(c-1) && c >= 3 => (ADDshiftLL x x [log64(c-1)]) +(MUL x (MOVDconst [c])) && isPowerOfTwo(c+1) && c >= 7 => (ADDshiftLL (NEG x) x [log64(c+1)]) +(MUL x (MOVDconst [c])) && c%3 == 0 && isPowerOfTwo(c/3) => (SLLconst [log64(c/3)] (ADDshiftLL x x [1])) +(MUL x (MOVDconst [c])) && c%5 == 0 && isPowerOfTwo(c/5) => (SLLconst [log64(c/5)] (ADDshiftLL x x [2])) +(MUL x (MOVDconst [c])) && c%7 == 0 && isPowerOfTwo(c/7) => (SLLconst [log64(c/7)] (ADDshiftLL (NEG x) x [3])) +(MUL x (MOVDconst [c])) && c%9 == 0 && isPowerOfTwo(c/9) => (SLLconst [log64(c/9)] (ADDshiftLL x x [3])) + +(MULW x (MOVDconst [c])) && int32(c)==-1 => (MOVWUreg (NEG x)) (MULW _ (MOVDconst [c])) && int32(c)==0 => (MOVDconst [0]) (MULW x (MOVDconst [c])) && int32(c)==1 => (MOVWUreg x) - -(MUL x (MOVDconst [c])) && canMulStrengthReduce(config, c) => {mulStrengthReduce(v, x, c)} -(MULW x (MOVDconst [c])) && v.Type.Size() <= 4 && canMulStrengthReduce32(config, int32(c)) => {mulStrengthReduce32(v, x, int32(c))} +(MULW x (MOVDconst [c])) && isPowerOfTwo(c) => (MOVWUreg (SLLconst [log64(c)] x)) +(MULW x (MOVDconst [c])) && isPowerOfTwo(c-1) && int32(c) >= 3 => (MOVWUreg (ADDshiftLL x x [log64(c-1)])) +(MULW x (MOVDconst [c])) && isPowerOfTwo(c+1) && int32(c) >= 7 => (MOVWUreg (ADDshiftLL (NEG x) x [log64(c+1)])) +(MULW x (MOVDconst [c])) && c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c) => (MOVWUreg (SLLconst [log64(c/3)] (ADDshiftLL x x [1]))) +(MULW x (MOVDconst [c])) && c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c) => (MOVWUreg (SLLconst [log64(c/5)] (ADDshiftLL x x [2]))) +(MULW x (MOVDconst [c])) && c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c) => (MOVWUreg (SLLconst [log64(c/7)] (ADDshiftLL (NEG x) x [3]))) +(MULW x (MOVDconst [c])) && c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c) => (MOVWUreg (SLLconst [log64(c/9)] (ADDshiftLL x x [3]))) // mneg by constant (MNEG x (MOVDconst [-1])) => x @@ -1198,7 +1198,6 @@ // generic simplifications (ADD x (NEG y)) => (SUB x y) -(SUB x (NEG y)) => (ADD x y) (SUB x x) => (MOVDconst [0]) (AND x x) => x (OR x x) => x @@ -1210,7 +1209,6 @@ (XOR x (MVN y)) => (EON x y) (OR x (MVN y)) => (ORN x y) (MVN (XOR x y)) => (EON x y) -(NEG (SUB x y)) => (SUB y x) (NEG (NEG x)) => x (CSEL [cc] (MOVDconst [-1]) (MOVDconst [0]) flag) => (CSETM [cc] flag) diff --git a/src/cmd/compile/internal/ssa/_gen/ARM64Ops.go b/src/cmd/compile/internal/ssa/_gen/ARM64Ops.go index ebb7ed52997c43..8ebbd7e95ef788 100644 --- a/src/cmd/compile/internal/ssa/_gen/ARM64Ops.go +++ b/src/cmd/compile/internal/ssa/_gen/ARM64Ops.go @@ -554,8 +554,8 @@ func init() { inputs: []regMask{buildReg("R20")}, clobbers: buildReg("R16 R17 R20 R30"), }, - //faultOnNilArg0: true, // Note: removed for 73748. TODO: reenable at some point - unsafePoint: true, // FP maintenance around DUFFZERO can be clobbered by interrupts + faultOnNilArg0: true, + unsafePoint: true, // FP maintenance around DUFFZERO can be clobbered by interrupts }, // large zeroing @@ -595,9 +595,9 @@ func init() { inputs: []regMask{buildReg("R21"), buildReg("R20")}, clobbers: buildReg("R16 R17 R20 R21 R26 R30"), }, - //faultOnNilArg0: true, // Note: removed for 73748. TODO: reenable at some point - //faultOnNilArg1: true, - unsafePoint: true, // FP maintenance around DUFFCOPY can be clobbered by interrupts + faultOnNilArg0: true, + faultOnNilArg1: true, + unsafePoint: true, // FP maintenance around DUFFCOPY can be clobbered by interrupts }, // large move diff --git a/src/cmd/compile/internal/ssa/_gen/ARM64latelower.rules b/src/cmd/compile/internal/ssa/_gen/ARM64latelower.rules index 8c43b960b9d964..613a23f6e4dd7a 100644 --- a/src/cmd/compile/internal/ssa/_gen/ARM64latelower.rules +++ b/src/cmd/compile/internal/ssa/_gen/ARM64latelower.rules @@ -96,8 +96,3 @@ // use zero register (MOVDconst [0]) => (ZERO) - -// Prefer addition when shifting left by one. -// They have the same latency, but ADD can often be done -// by more functional units in the processor. -(SLLconst [1] x) => (ADD x x) diff --git a/src/cmd/compile/internal/ssa/_gen/LOONG64.rules b/src/cmd/compile/internal/ssa/_gen/LOONG64.rules index cab63a503f3e9c..7fc40577ba8d67 100644 --- a/src/cmd/compile/internal/ssa/_gen/LOONG64.rules +++ b/src/cmd/compile/internal/ssa/_gen/LOONG64.rules @@ -776,24 +776,11 @@ // generic simplifications (ADDV x (NEGV y)) => (SUBV x y) -(SUBV x (NEGV y)) => (ADDV x y) (SUBV x x) => (MOVVconst [0]) (SUBV (MOVVconst [0]) x) => (NEGV x) (AND x x) => x (OR x x) => x (XOR x x) => (MOVVconst [0]) -(ORN x (MOVVconst [-1])) => x -(AND x (NORconst [0] y)) => (ANDN x y) -(OR x (NORconst [0] y)) => (ORN x y) - -// Fold negation into subtraction. -(NEGV (SUBV x y)) => (SUBV y x) -(NEGV s:(ADDVconst [c] (SUBV x y))) && s.Uses == 1 && is12Bit(-c) => (ADDVconst [-c] (SUBV y x)) - -// Double negation. -(NEGV (NEGV x)) => x -// Fold NEGV into ADDVconst. Take care to keep c in 12 bit range. -(NEGV s:(ADDVconst [c] (NEGV x))) && s.Uses == 1 && is12Bit(-c) => (ADDVconst [-c] x) // remove redundant *const ops (ADDVconst [0] x) => x @@ -843,22 +830,6 @@ (MOVBUreg (ANDconst [c] x)) => (ANDconst [c&0xff] x) -// Prefetch instructions (hint specified using aux field) -// For PRELD{,X} A value of hint indicates: -// hint=0 is defined as load prefetch to L1-cache -// hint=2 is defined as load prefetch to L3-cache -// The PrefetchCacheStreamed implementation prefetches 512 bytes of data -// into L3. The aux field are defined as follows: -// bit[4:0]: -// $hint parameter of PRELDX instruction -// bit[41:5]: -// $n parameter of PRELDX instruction, bit[0] of $n is the address -// sequence, bits[11:1] is the block size, bits[20:12] is the block -// num, bits[36:21] is the stride, for more details about $n, refer -// to src/cmd/internal/obj/loong64/doc.go -(PrefetchCache addr mem) => (PRELD addr mem [0]) -(PrefetchCacheStreamed addr mem) => (PRELDX addr mem [(((512 << 1) + (1 << 12)) << 5) + 2]) - // constant comparisons (SGTconst [c] (MOVVconst [d])) && c>d => (MOVVconst [1]) (SGTconst [c] (MOVVconst [d])) && c<=d => (MOVVconst [0]) diff --git a/src/cmd/compile/internal/ssa/_gen/LOONG64Ops.go b/src/cmd/compile/internal/ssa/_gen/LOONG64Ops.go index 5ef304b4f93ac1..c68a24ca97d03a 100644 --- a/src/cmd/compile/internal/ssa/_gen/LOONG64Ops.go +++ b/src/cmd/compile/internal/ssa/_gen/LOONG64Ops.go @@ -148,7 +148,6 @@ func init() { gpstore2 = regInfo{inputs: []regMask{gpspsbg, gpg, gpg}} gpxchg = regInfo{inputs: []regMask{gpspsbg, gpg}, outputs: []regMask{gp}} gpcas = regInfo{inputs: []regMask{gpspsbg, gpg, gpg}, outputs: []regMask{gp}} - preldreg = regInfo{inputs: []regMask{gpspg}} fp01 = regInfo{inputs: nil, outputs: []regMask{fp}} fp11 = regInfo{inputs: []regMask{fp}, outputs: []regMask{fp}} fp21 = regInfo{inputs: []regMask{fp, fp}, outputs: []regMask{fp}} @@ -221,8 +220,6 @@ func init() { {name: "XORconst", argLength: 1, reg: gp11, asm: "XOR", aux: "Int64", typ: "UInt64"}, // arg0 ^ auxInt {name: "NOR", argLength: 2, reg: gp21, asm: "NOR", commutative: true}, // ^(arg0 | arg1) {name: "NORconst", argLength: 1, reg: gp11, asm: "NOR", aux: "Int64"}, // ^(arg0 | auxInt) - {name: "ANDN", argLength: 2, reg: gp21, asm: "ANDN"}, // arg0 & ^arg1 - {name: "ORN", argLength: 2, reg: gp21, asm: "ORN"}, // arg0 | ^arg1 {name: "FMADDF", argLength: 3, reg: fp31, asm: "FMADDF", commutative: true, typ: "Float32"}, // (arg0 * arg1) + arg2 {name: "FMADDD", argLength: 3, reg: fp31, asm: "FMADDD", commutative: true, typ: "Float64"}, // (arg0 * arg1) + arg2 @@ -569,14 +566,6 @@ func init() { {name: "LoweredPanicBoundsA", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r3, r4}}, typ: "Mem", call: true}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in genericOps.go). {name: "LoweredPanicBoundsB", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r2, r3}}, typ: "Mem", call: true}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in genericOps.go). {name: "LoweredPanicBoundsC", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r1, r2}}, typ: "Mem", call: true}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in genericOps.go). - - // Prefetch instruction - // Do prefetch arg0 address with option aux. arg0=addr, arg1=memory, aux=option. - // Note: - // The aux of PRELDX is actually composed of two values: $hint and $n. bit[4:0] - // is $hint and bit[41:5] is $n. - {name: "PRELD", argLength: 2, aux: "Int64", reg: preldreg, asm: "PRELD", hasSideEffects: true}, - {name: "PRELDX", argLength: 2, aux: "Int64", reg: preldreg, asm: "PRELDX", hasSideEffects: true}, } blocks := []blockData{ diff --git a/src/cmd/compile/internal/ssa/_gen/MIPS.rules b/src/cmd/compile/internal/ssa/_gen/MIPS.rules index a9bac5fabe1b72..4471763462f3a9 100644 --- a/src/cmd/compile/internal/ssa/_gen/MIPS.rules +++ b/src/cmd/compile/internal/ssa/_gen/MIPS.rules @@ -420,9 +420,6 @@ // Write barrier. (WB ...) => (LoweredWB ...) -// Publication barrier as intrinsic -(PubBarrier ...) => (LoweredPubBarrier ...) - (PanicBounds [kind] x y mem) && boundsABI(kind) == 0 => (LoweredPanicBoundsA [kind] x y mem) (PanicBounds [kind] x y mem) && boundsABI(kind) == 1 => (LoweredPanicBoundsB [kind] x y mem) (PanicBounds [kind] x y mem) && boundsABI(kind) == 2 => (LoweredPanicBoundsC [kind] x y mem) @@ -617,14 +614,11 @@ // generic simplifications (ADD x (NEG y)) => (SUB x y) -(SUB x (NEG y)) => (ADD x y) (SUB x x) => (MOVWconst [0]) (SUB (MOVWconst [0]) x) => (NEG x) (AND x x) => x (OR x x) => x (XOR x x) => (MOVWconst [0]) -(NEG (SUB x y)) => (SUB y x) -(NEG (NEG x)) => x // miscellaneous patterns generated by dec64 (AND (SGTUconst [1] x) (SGTUconst [1] y)) => (SGTUconst [1] (OR x y)) diff --git a/src/cmd/compile/internal/ssa/_gen/MIPS64.rules b/src/cmd/compile/internal/ssa/_gen/MIPS64.rules index 8e484f4a3d3182..5b55c3bef75e9c 100644 --- a/src/cmd/compile/internal/ssa/_gen/MIPS64.rules +++ b/src/cmd/compile/internal/ssa/_gen/MIPS64.rules @@ -476,9 +476,6 @@ // Write barrier. (WB ...) => (LoweredWB ...) -// Publication barrier as intrinsic -(PubBarrier ...) => (LoweredPubBarrier ...) - (PanicBounds [kind] x y mem) && boundsABI(kind) == 0 => (LoweredPanicBoundsA [kind] x y mem) (PanicBounds [kind] x y mem) && boundsABI(kind) == 1 => (LoweredPanicBoundsB [kind] x y mem) (PanicBounds [kind] x y mem) && boundsABI(kind) == 2 => (LoweredPanicBoundsC [kind] x y mem) @@ -722,14 +719,11 @@ // generic simplifications (ADDV x (NEGV y)) => (SUBV x y) -(SUBV x (NEGV y)) => (ADDV x y) (SUBV x x) => (MOVVconst [0]) (SUBV (MOVVconst [0]) x) => (NEGV x) (AND x x) => x (OR x x) => x (XOR x x) => (MOVVconst [0]) -(NEGV (SUBV x y)) => (SUBV y x) -(NEGV (NEGV x)) => x // remove redundant *const ops (ADDVconst [0] x) => x diff --git a/src/cmd/compile/internal/ssa/_gen/MIPS64Ops.go b/src/cmd/compile/internal/ssa/_gen/MIPS64Ops.go index 6c04a1aea26d80..3d1abb16b60e79 100644 --- a/src/cmd/compile/internal/ssa/_gen/MIPS64Ops.go +++ b/src/cmd/compile/internal/ssa/_gen/MIPS64Ops.go @@ -466,9 +466,6 @@ func init() { // Returns a pointer to a write barrier buffer in R25. {name: "LoweredWB", argLength: 1, reg: regInfo{clobbers: (callerSave &^ gpg) | buildReg("R31"), outputs: []regMask{buildReg("R25")}}, clobberFlags: true, aux: "Int64"}, - // Do data barrier. arg0=memorys - {name: "LoweredPubBarrier", argLength: 1, asm: "SYNC", hasSideEffects: true}, - // There are three of these functions so that they can have three different register inputs. // When we check 0 <= c <= cap (A), then 0 <= b <= c (B), then 0 <= a <= b (C), we want the // default registers to match so we don't need to copy registers around unnecessarily. diff --git a/src/cmd/compile/internal/ssa/_gen/MIPSOps.go b/src/cmd/compile/internal/ssa/_gen/MIPSOps.go index 62c35ed49f2a85..48e06a4189ed89 100644 --- a/src/cmd/compile/internal/ssa/_gen/MIPSOps.go +++ b/src/cmd/compile/internal/ssa/_gen/MIPSOps.go @@ -408,9 +408,6 @@ func init() { // Returns a pointer to a write barrier buffer in R25. {name: "LoweredWB", argLength: 1, reg: regInfo{clobbers: (callerSave &^ gpg) | buildReg("R31"), outputs: []regMask{buildReg("R25")}}, clobberFlags: true, aux: "Int64"}, - // Do data barrier. arg0=memorys - {name: "LoweredPubBarrier", argLength: 1, asm: "SYNC", hasSideEffects: true}, - // There are three of these functions so that they can have three different register inputs. // When we check 0 <= c <= cap (A), then 0 <= b <= c (B), then 0 <= a <= b (C), we want the // default registers to match so we don't need to copy registers around unnecessarily. diff --git a/src/cmd/compile/internal/ssa/_gen/README b/src/cmd/compile/internal/ssa/_gen/README index a8242f93527097..74b81c2814330c 100644 --- a/src/cmd/compile/internal/ssa/_gen/README +++ b/src/cmd/compile/internal/ssa/_gen/README @@ -9,8 +9,3 @@ more information. To regenerate everything, run "go generate" on the ssa package in the parent directory. - -The parent directory contains a test in generate_test.go that will fail -if the generated files are not up-to-date, and to allow that test to -run in no-network environments, golang.org/x/tools/go/ast/astutil is -vendored. diff --git a/src/cmd/compile/internal/ssa/_gen/RISCV64.rules b/src/cmd/compile/internal/ssa/_gen/RISCV64.rules index dc1cc97fb3cd05..a5d4fb72ec687f 100644 --- a/src/cmd/compile/internal/ssa/_gen/RISCV64.rules +++ b/src/cmd/compile/internal/ssa/_gen/RISCV64.rules @@ -231,17 +231,6 @@ (BitLen16 x) => (BitLen64 (ZeroExt16to64 x)) (BitLen8 x) => (BitLen64 (ZeroExt8to64 x)) -// Byte swap (note that these will only be emitted for rva22u64 and above). -(Bswap64 ...) => (REV8 ...) -(Bswap32 x) => (SRLI [32] (REV8 x)) -(Bswap16 x) => (SRLI [48] (REV8 x)) - -// Population count (note that these will be emitted with guards for rva20u64). -(PopCount64 ...) => (CPOP ...) -(PopCount32 ...) => (CPOPW ...) -(PopCount16 x) => (CPOP (ZeroExt16to64 x)) -(PopCount8 x) => (CPOP (ZeroExt8to64 x)) - (Less64 ...) => (SLT ...) (Less32 x y) => (SLT (SignExt32to64 x) (SignExt32to64 y)) (Less16 x y) => (SLT (SignExt16to64 x) (SignExt16to64 y)) @@ -743,15 +732,6 @@ (ROL x (NEG y)) => (ROR x y) (ROLW x (NEG y)) => (RORW x y) -// generic simplifications -(ADD x (NEG y)) => (SUB x y) -(SUB x (NEG y)) => (ADD x y) -(SUB x x) => (MOVDconst [0]) -(AND x x) => x -(OR x x) => x -(ORN x x) => (MOVDconst [-1]) -(XOR x x) => (MOVDconst [0]) - // Convert const subtraction into ADDI with negative immediate, where possible. (SUB x (MOVDconst [val])) && is32Bit(-val) => (ADDI [-val] x) (SUB (MOVDconst [val]) y) && is32Bit(-val) => (NEG (ADDI [-val] y)) diff --git a/src/cmd/compile/internal/ssa/_gen/RISCV64Ops.go b/src/cmd/compile/internal/ssa/_gen/RISCV64Ops.go index 8cb042a604bee6..cc2302ff374fa5 100644 --- a/src/cmd/compile/internal/ssa/_gen/RISCV64Ops.go +++ b/src/cmd/compile/internal/ssa/_gen/RISCV64Ops.go @@ -231,15 +231,12 @@ func init() { {name: "ANDI", argLength: 1, reg: gp11, asm: "ANDI", aux: "Int64"}, // arg0 & auxint {name: "CLZ", argLength: 1, reg: gp11, asm: "CLZ"}, // count leading zeros {name: "CLZW", argLength: 1, reg: gp11, asm: "CLZW"}, // count leading zeros of least significant word - {name: "CPOP", argLength: 1, reg: gp11, asm: "CPOP"}, // count set bits - {name: "CPOPW", argLength: 1, reg: gp11, asm: "CPOPW"}, // count set bits in least significant word {name: "CTZ", argLength: 1, reg: gp11, asm: "CTZ"}, // count trailing zeros {name: "CTZW", argLength: 1, reg: gp11, asm: "CTZW"}, // count trailing zeros of least significant word {name: "NOT", argLength: 1, reg: gp11, asm: "NOT"}, // ^arg0 {name: "OR", argLength: 2, reg: gp21, asm: "OR", commutative: true}, // arg0 | arg1 {name: "ORN", argLength: 2, reg: gp21, asm: "ORN"}, // ^arg0 | arg1 {name: "ORI", argLength: 1, reg: gp11, asm: "ORI", aux: "Int64"}, // arg0 | auxint - {name: "REV8", argLength: 1, reg: gp11, asm: "REV8"}, // reverse bytes {name: "ROL", argLength: 2, reg: gp21, asm: "ROL"}, // rotate left arg0 by (arg1 & 63) {name: "ROLW", argLength: 2, reg: gp21, asm: "ROLW"}, // rotate left least significant word of arg0 by (arg1 & 31), sign extended {name: "ROR", argLength: 2, reg: gp21, asm: "ROR"}, // rotate right arg0 by (arg1 & 63) diff --git a/src/cmd/compile/internal/ssa/_gen/S390X.rules b/src/cmd/compile/internal/ssa/_gen/S390X.rules index 231ad0615dd96e..78de5bb5a22296 100644 --- a/src/cmd/compile/internal/ssa/_gen/S390X.rules +++ b/src/cmd/compile/internal/ssa/_gen/S390X.rules @@ -1188,8 +1188,6 @@ // TODO: more of this (ADD x (NEG y)) => (SUB x y) (ADDW x (NEGW y)) => (SUBW x y) -(SUB x (NEG y)) => (ADD x y) -(SUBW x (NEGW y)) => (ADDW x y) (SUB x x) => (MOVDconst [0]) (SUBW x x) => (MOVDconst [0]) (AND x x) => x @@ -1198,7 +1196,6 @@ (ORW x x) => x (XOR x x) => (MOVDconst [0]) (XORW x x) => (MOVDconst [0]) -(NEG (NEG x)) => x (NEG (ADDconst [c] (NEG x))) && c != -(1<<31) => (ADDconst [-c] x) (MOVBZreg (ANDWconst [m] x)) => (MOVWZreg (ANDWconst [int32( uint8(m))] x)) (MOVHZreg (ANDWconst [m] x)) => (MOVWZreg (ANDWconst [int32(uint16(m))] x)) diff --git a/src/cmd/compile/internal/ssa/_gen/allocators.go b/src/cmd/compile/internal/ssa/_gen/allocators.go index 38acc5133abe86..56e6d69a312e1d 100644 --- a/src/cmd/compile/internal/ssa/_gen/allocators.go +++ b/src/cmd/compile/internal/ssa/_gen/allocators.go @@ -41,7 +41,7 @@ func genAllocators() { capacity: "cap(%s)", mak: "make([]*Value, %s)", resize: "%s[:%s]", - clear: "clear(%s)", + clear: "for i := range %[1]s {\n%[1]s[i] = nil\n}", minLog: 5, maxLog: 32, }, @@ -51,7 +51,7 @@ func genAllocators() { capacity: "cap(%s)", mak: "make([]limit, %s)", resize: "%s[:%s]", - clear: "clear(%s)", + clear: "for i := range %[1]s {\n%[1]s[i] = limit{}\n}", minLog: 3, maxLog: 30, }, @@ -155,7 +155,7 @@ func genAllocators() { panic(err) } - if err := os.WriteFile(outFile("allocators.go"), b, 0666); err != nil { + if err := os.WriteFile("../allocators.go", b, 0666); err != nil { log.Fatalf("can't write output: %v\n", err) } } diff --git a/src/cmd/compile/internal/ssa/_gen/generic.rules b/src/cmd/compile/internal/ssa/_gen/generic.rules index b178a1add6de29..eb04d03e496f5e 100644 --- a/src/cmd/compile/internal/ssa/_gen/generic.rules +++ b/src/cmd/compile/internal/ssa/_gen/generic.rules @@ -139,10 +139,6 @@ (Mul64 (Const64 [c]) (Const64 [d])) => (Const64 [c*d]) (Mul32F (Const32F [c]) (Const32F [d])) && c*d == c*d => (Const32F [c*d]) (Mul64F (Const64F [c]) (Const64F [d])) && c*d == c*d => (Const64F [c*d]) -(Mul32uhilo (Const32 [c]) (Const32 [d])) => (MakeTuple (Const32 [bitsMulU32(c, d).hi]) (Const32 [bitsMulU32(c,d).lo])) -(Mul64uhilo (Const64 [c]) (Const64 [d])) => (MakeTuple (Const64 [bitsMulU64(c, d).hi]) (Const64 [bitsMulU64(c,d).lo])) -(Mul32uover (Const32 [c]) (Const32 [d])) => (MakeTuple (Const32 [bitsMulU32(c, d).lo]) (ConstBool [bitsMulU32(c,d).hi != 0])) -(Mul64uover (Const64 [c]) (Const64 [d])) => (MakeTuple (Const64 [bitsMulU64(c, d).lo]) (ConstBool [bitsMulU64(c,d).hi != 0])) (And8 (Const8 [c]) (Const8 [d])) => (Const8 [c&d]) (And16 (Const16 [c]) (Const16 [d])) => (Const16 [c&d]) @@ -2832,14 +2828,3 @@ && clobber(sbts) && clobber(key) => (StaticLECall {f} [argsize] typ_ map_ (StringMake ptr len) mem) - -// Similarly to map lookups, also handle unique.Make for strings, which unique.Make will clone. -(StaticLECall {f} [argsize] dict_ key:(SelectN [0] sbts:(StaticLECall {g} _ ptr len mem)) m:(SelectN [1] sbts)) - && isSameCall(f, "unique.Make[go.shape.string]") - && isSameCall(g, "runtime.slicebytetostring") - && key.Uses == 1 - && sbts.Uses == 2 - && resetCopy(m, mem) - && clobber(sbts) - && clobber(key) -=> (StaticLECall {f} [argsize] dict_ (StringMake ptr len) mem) diff --git a/src/cmd/compile/internal/ssa/_gen/main.go b/src/cmd/compile/internal/ssa/_gen/main.go index f20603245ba321..3f65831b6e02b5 100644 --- a/src/cmd/compile/internal/ssa/_gen/main.go +++ b/src/cmd/compile/internal/ssa/_gen/main.go @@ -113,7 +113,6 @@ var archs []arch var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to `file`") var memprofile = flag.String("memprofile", "", "write memory profile to `file`") var tracefile = flag.String("trace", "", "write trace to `file`") -var outDir = flag.String("outdir", "..", "directory in which to write generated files") func main() { flag.Parse() @@ -145,13 +144,6 @@ func main() { defer trace.Stop() } - if *outDir != ".." { - err := os.MkdirAll(*outDir, 0755) - if err != nil { - log.Fatalf("failed to create output directory: %v", err) - } - } - slices.SortFunc(archs, func(a, b arch) int { return strings.Compare(a.name, b.name) }) @@ -201,10 +193,6 @@ func main() { } } -func outFile(file string) string { - return *outDir + "/" + file -} - func genOp() { w := new(bytes.Buffer) fmt.Fprintf(w, "// Code generated from _gen/*Ops.go using 'go generate'; DO NOT EDIT.\n") @@ -512,7 +500,7 @@ func genOp() { panic(err) } - if err := os.WriteFile(outFile("opGen.go"), b, 0666); err != nil { + if err := os.WriteFile("../opGen.go", b, 0666); err != nil { log.Fatalf("can't write output: %v\n", err) } diff --git a/src/cmd/compile/internal/ssa/_gen/rulegen.go b/src/cmd/compile/internal/ssa/_gen/rulegen.go index 3854d58b7f9e56..5f5967a142253e 100644 --- a/src/cmd/compile/internal/ssa/_gen/rulegen.go +++ b/src/cmd/compile/internal/ssa/_gen/rulegen.go @@ -50,7 +50,6 @@ import ( // special rules: trailing ellipsis "..." (in the outermost sexpr?) must match on both sides of a rule. // trailing three underscore "___" in the outermost match sexpr indicate the presence of // extra ignored args that need not appear in the replacement -// if the right-hand side is in {}, then it is code used to generate the result. // extra conditions is just a chunk of Go that evaluates to a boolean. It may use // variables declared in the matching tsexpr. The variable "v" is predefined to be @@ -322,7 +321,7 @@ func genRulesSuffix(arch arch, suff string) { file = astutil.Apply(file, pre, post).(*ast.File) // Write the well-formatted source to file - f, err := os.Create(outFile("rewrite" + arch.name + suff + ".go")) + f, err := os.Create("../rewrite" + arch.name + suff + ".go") if err != nil { log.Fatalf("can't write output: %v", err) } @@ -1183,11 +1182,6 @@ func genResult(rr *RuleRewrite, arch arch, result, pos string) { rr.add(stmtf("b = %s", s[0])) result = s[1] } - if result[0] == '{' { - // Arbitrary code used to make the result - rr.add(stmtf("v.copyOf(%s)", result[1:len(result)-1])) - return - } cse := make(map[string]string) genResult0(rr, arch, result, true, move, pos, cse) } diff --git a/src/cmd/compile/internal/ssa/_gen/vendor/golang.org/x/tools/LICENSE b/src/cmd/compile/internal/ssa/_gen/vendor/golang.org/x/tools/LICENSE deleted file mode 100644 index 2a7cf70da6e498..00000000000000 --- a/src/cmd/compile/internal/ssa/_gen/vendor/golang.org/x/tools/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright 2009 The Go Authors. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google LLC nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/cmd/compile/internal/ssa/_gen/vendor/golang.org/x/tools/PATENTS b/src/cmd/compile/internal/ssa/_gen/vendor/golang.org/x/tools/PATENTS deleted file mode 100644 index 733099041f84fa..00000000000000 --- a/src/cmd/compile/internal/ssa/_gen/vendor/golang.org/x/tools/PATENTS +++ /dev/null @@ -1,22 +0,0 @@ -Additional IP Rights Grant (Patents) - -"This implementation" means the copyrightable works distributed by -Google as part of the Go project. - -Google hereby grants to You a perpetual, worldwide, non-exclusive, -no-charge, royalty-free, irrevocable (except as stated in this section) -patent license to make, have made, use, offer to sell, sell, import, -transfer and otherwise run, modify and propagate the contents of this -implementation of Go, where such license applies only to those patent -claims, both currently owned or controlled by Google and acquired in -the future, licensable by Google that are necessarily infringed by this -implementation of Go. This grant does not include claims that would be -infringed only as a consequence of further modification of this -implementation. If you or your agent or exclusive licensee institute or -order or agree to the institution of patent litigation against any -entity (including a cross-claim or counterclaim in a lawsuit) alleging -that this implementation of Go or any code incorporated within this -implementation of Go constitutes direct or contributory patent -infringement, or inducement of patent infringement, then any patent -rights granted to you under this License for this implementation of Go -shall terminate as of the date such litigation is filed. diff --git a/src/cmd/compile/internal/ssa/_gen/vendor/golang.org/x/tools/go/ast/astutil/enclosing.go b/src/cmd/compile/internal/ssa/_gen/vendor/golang.org/x/tools/go/ast/astutil/enclosing.go deleted file mode 100644 index 6e34df46130b75..00000000000000 --- a/src/cmd/compile/internal/ssa/_gen/vendor/golang.org/x/tools/go/ast/astutil/enclosing.go +++ /dev/null @@ -1,654 +0,0 @@ -// Copyright 2013 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 astutil - -// This file defines utilities for working with source positions. - -import ( - "fmt" - "go/ast" - "go/token" - "sort" -) - -// PathEnclosingInterval returns the node that encloses the source -// interval [start, end), and all its ancestors up to the AST root. -// -// The definition of "enclosing" used by this function considers -// additional whitespace abutting a node to be enclosed by it. -// In this example: -// -// z := x + y // add them -// <-A-> -// <----B-----> -// -// the ast.BinaryExpr(+) node is considered to enclose interval B -// even though its [Pos()..End()) is actually only interval A. -// This behaviour makes user interfaces more tolerant of imperfect -// input. -// -// This function treats tokens as nodes, though they are not included -// in the result. e.g. PathEnclosingInterval("+") returns the -// enclosing ast.BinaryExpr("x + y"). -// -// If start==end, the 1-char interval following start is used instead. -// -// The 'exact' result is true if the interval contains only path[0] -// and perhaps some adjacent whitespace. It is false if the interval -// overlaps multiple children of path[0], or if it contains only -// interior whitespace of path[0]. -// In this example: -// -// z := x + y // add them -// <--C--> <---E--> -// ^ -// D -// -// intervals C, D and E are inexact. C is contained by the -// z-assignment statement, because it spans three of its children (:=, -// x, +). So too is the 1-char interval D, because it contains only -// interior whitespace of the assignment. E is considered interior -// whitespace of the BlockStmt containing the assignment. -// -// The resulting path is never empty; it always contains at least the -// 'root' *ast.File. Ideally PathEnclosingInterval would reject -// intervals that lie wholly or partially outside the range of the -// file, but unfortunately ast.File records only the token.Pos of -// the 'package' keyword, but not of the start of the file itself. -func PathEnclosingInterval(root *ast.File, start, end token.Pos) (path []ast.Node, exact bool) { - // fmt.Printf("EnclosingInterval %d %d\n", start, end) // debugging - - // Precondition: node.[Pos..End) and adjoining whitespace contain [start, end). - var visit func(node ast.Node) bool - visit = func(node ast.Node) bool { - path = append(path, node) - - nodePos := node.Pos() - nodeEnd := node.End() - - // fmt.Printf("visit(%T, %d, %d)\n", node, nodePos, nodeEnd) // debugging - - // Intersect [start, end) with interval of node. - if start < nodePos { - start = nodePos - } - if end > nodeEnd { - end = nodeEnd - } - - // Find sole child that contains [start, end). - children := childrenOf(node) - l := len(children) - for i, child := range children { - // [childPos, childEnd) is unaugmented interval of child. - childPos := child.Pos() - childEnd := child.End() - - // [augPos, augEnd) is whitespace-augmented interval of child. - augPos := childPos - augEnd := childEnd - if i > 0 { - augPos = children[i-1].End() // start of preceding whitespace - } - if i < l-1 { - nextChildPos := children[i+1].Pos() - // Does [start, end) lie between child and next child? - if start >= augEnd && end <= nextChildPos { - return false // inexact match - } - augEnd = nextChildPos // end of following whitespace - } - - // fmt.Printf("\tchild %d: [%d..%d)\tcontains interval [%d..%d)?\n", - // i, augPos, augEnd, start, end) // debugging - - // Does augmented child strictly contain [start, end)? - if augPos <= start && end <= augEnd { - if is[tokenNode](child) { - return true - } - - // childrenOf elides the FuncType node beneath FuncDecl. - // Add it back here for TypeParams, Params, Results, - // all FieldLists). But we don't add it back for the "func" token - // even though it is is the tree at FuncDecl.Type.Func. - if decl, ok := node.(*ast.FuncDecl); ok { - if fields, ok := child.(*ast.FieldList); ok && fields != decl.Recv { - path = append(path, decl.Type) - } - } - - return visit(child) - } - - // Does [start, end) overlap multiple children? - // i.e. left-augmented child contains start - // but LR-augmented child does not contain end. - if start < childEnd && end > augEnd { - break - } - } - - // No single child contained [start, end), - // so node is the result. Is it exact? - - // (It's tempting to put this condition before the - // child loop, but it gives the wrong result in the - // case where a node (e.g. ExprStmt) and its sole - // child have equal intervals.) - if start == nodePos && end == nodeEnd { - return true // exact match - } - - return false // inexact: overlaps multiple children - } - - // Ensure [start,end) is nondecreasing. - if start > end { - start, end = end, start - } - - if start < root.End() && end > root.Pos() { - if start == end { - end = start + 1 // empty interval => interval of size 1 - } - exact = visit(root) - - // Reverse the path: - for i, l := 0, len(path); i < l/2; i++ { - path[i], path[l-1-i] = path[l-1-i], path[i] - } - } else { - // Selection lies within whitespace preceding the - // first (or following the last) declaration in the file. - // The result nonetheless always includes the ast.File. - path = append(path, root) - } - - return -} - -// tokenNode is a dummy implementation of ast.Node for a single token. -// They are used transiently by PathEnclosingInterval but never escape -// this package. -type tokenNode struct { - pos token.Pos - end token.Pos -} - -func (n tokenNode) Pos() token.Pos { - return n.pos -} - -func (n tokenNode) End() token.Pos { - return n.end -} - -func tok(pos token.Pos, len int) ast.Node { - return tokenNode{pos, pos + token.Pos(len)} -} - -// childrenOf returns the direct non-nil children of ast.Node n. -// It may include fake ast.Node implementations for bare tokens. -// it is not safe to call (e.g.) ast.Walk on such nodes. -func childrenOf(n ast.Node) []ast.Node { - var children []ast.Node - - // First add nodes for all true subtrees. - ast.Inspect(n, func(node ast.Node) bool { - if node == n { // push n - return true // recur - } - if node != nil { // push child - children = append(children, node) - } - return false // no recursion - }) - - // Then add fake Nodes for bare tokens. - switch n := n.(type) { - case *ast.ArrayType: - children = append(children, - tok(n.Lbrack, len("[")), - tok(n.Elt.End(), len("]"))) - - case *ast.AssignStmt: - children = append(children, - tok(n.TokPos, len(n.Tok.String()))) - - case *ast.BasicLit: - children = append(children, - tok(n.ValuePos, len(n.Value))) - - case *ast.BinaryExpr: - children = append(children, tok(n.OpPos, len(n.Op.String()))) - - case *ast.BlockStmt: - children = append(children, - tok(n.Lbrace, len("{")), - tok(n.Rbrace, len("}"))) - - case *ast.BranchStmt: - children = append(children, - tok(n.TokPos, len(n.Tok.String()))) - - case *ast.CallExpr: - children = append(children, - tok(n.Lparen, len("(")), - tok(n.Rparen, len(")"))) - if n.Ellipsis != 0 { - children = append(children, tok(n.Ellipsis, len("..."))) - } - - case *ast.CaseClause: - if n.List == nil { - children = append(children, - tok(n.Case, len("default"))) - } else { - children = append(children, - tok(n.Case, len("case"))) - } - children = append(children, tok(n.Colon, len(":"))) - - case *ast.ChanType: - switch n.Dir { - case ast.RECV: - children = append(children, tok(n.Begin, len("<-chan"))) - case ast.SEND: - children = append(children, tok(n.Begin, len("chan<-"))) - case ast.RECV | ast.SEND: - children = append(children, tok(n.Begin, len("chan"))) - } - - case *ast.CommClause: - if n.Comm == nil { - children = append(children, - tok(n.Case, len("default"))) - } else { - children = append(children, - tok(n.Case, len("case"))) - } - children = append(children, tok(n.Colon, len(":"))) - - case *ast.Comment: - // nop - - case *ast.CommentGroup: - // nop - - case *ast.CompositeLit: - children = append(children, - tok(n.Lbrace, len("{")), - tok(n.Rbrace, len("{"))) - - case *ast.DeclStmt: - // nop - - case *ast.DeferStmt: - children = append(children, - tok(n.Defer, len("defer"))) - - case *ast.Ellipsis: - children = append(children, - tok(n.Ellipsis, len("..."))) - - case *ast.EmptyStmt: - // nop - - case *ast.ExprStmt: - // nop - - case *ast.Field: - // TODO(adonovan): Field.{Doc,Comment,Tag}? - - case *ast.FieldList: - children = append(children, - tok(n.Opening, len("(")), // or len("[") - tok(n.Closing, len(")"))) // or len("]") - - case *ast.File: - // TODO test: Doc - children = append(children, - tok(n.Package, len("package"))) - - case *ast.ForStmt: - children = append(children, - tok(n.For, len("for"))) - - case *ast.FuncDecl: - // TODO(adonovan): FuncDecl.Comment? - - // Uniquely, FuncDecl breaks the invariant that - // preorder traversal yields tokens in lexical order: - // in fact, FuncDecl.Recv precedes FuncDecl.Type.Func. - // - // As a workaround, we inline the case for FuncType - // here and order things correctly. - // We also need to insert the elided FuncType just - // before the 'visit' recursion. - // - children = nil // discard ast.Walk(FuncDecl) info subtrees - children = append(children, tok(n.Type.Func, len("func"))) - if n.Recv != nil { - children = append(children, n.Recv) - } - children = append(children, n.Name) - if tparams := n.Type.TypeParams; tparams != nil { - children = append(children, tparams) - } - if n.Type.Params != nil { - children = append(children, n.Type.Params) - } - if n.Type.Results != nil { - children = append(children, n.Type.Results) - } - if n.Body != nil { - children = append(children, n.Body) - } - - case *ast.FuncLit: - // nop - - case *ast.FuncType: - if n.Func != 0 { - children = append(children, - tok(n.Func, len("func"))) - } - - case *ast.GenDecl: - children = append(children, - tok(n.TokPos, len(n.Tok.String()))) - if n.Lparen != 0 { - children = append(children, - tok(n.Lparen, len("(")), - tok(n.Rparen, len(")"))) - } - - case *ast.GoStmt: - children = append(children, - tok(n.Go, len("go"))) - - case *ast.Ident: - children = append(children, - tok(n.NamePos, len(n.Name))) - - case *ast.IfStmt: - children = append(children, - tok(n.If, len("if"))) - - case *ast.ImportSpec: - // TODO(adonovan): ImportSpec.{Doc,EndPos}? - - case *ast.IncDecStmt: - children = append(children, - tok(n.TokPos, len(n.Tok.String()))) - - case *ast.IndexExpr: - children = append(children, - tok(n.Lbrack, len("[")), - tok(n.Rbrack, len("]"))) - - case *ast.IndexListExpr: - children = append(children, - tok(n.Lbrack, len("[")), - tok(n.Rbrack, len("]"))) - - case *ast.InterfaceType: - children = append(children, - tok(n.Interface, len("interface"))) - - case *ast.KeyValueExpr: - children = append(children, - tok(n.Colon, len(":"))) - - case *ast.LabeledStmt: - children = append(children, - tok(n.Colon, len(":"))) - - case *ast.MapType: - children = append(children, - tok(n.Map, len("map"))) - - case *ast.ParenExpr: - children = append(children, - tok(n.Lparen, len("(")), - tok(n.Rparen, len(")"))) - - case *ast.RangeStmt: - children = append(children, - tok(n.For, len("for")), - tok(n.TokPos, len(n.Tok.String()))) - - case *ast.ReturnStmt: - children = append(children, - tok(n.Return, len("return"))) - - case *ast.SelectStmt: - children = append(children, - tok(n.Select, len("select"))) - - case *ast.SelectorExpr: - // nop - - case *ast.SendStmt: - children = append(children, - tok(n.Arrow, len("<-"))) - - case *ast.SliceExpr: - children = append(children, - tok(n.Lbrack, len("[")), - tok(n.Rbrack, len("]"))) - - case *ast.StarExpr: - children = append(children, tok(n.Star, len("*"))) - - case *ast.StructType: - children = append(children, tok(n.Struct, len("struct"))) - - case *ast.SwitchStmt: - children = append(children, tok(n.Switch, len("switch"))) - - case *ast.TypeAssertExpr: - children = append(children, - tok(n.Lparen-1, len(".")), - tok(n.Lparen, len("(")), - tok(n.Rparen, len(")"))) - - case *ast.TypeSpec: - // TODO(adonovan): TypeSpec.{Doc,Comment}? - - case *ast.TypeSwitchStmt: - children = append(children, tok(n.Switch, len("switch"))) - - case *ast.UnaryExpr: - children = append(children, tok(n.OpPos, len(n.Op.String()))) - - case *ast.ValueSpec: - // TODO(adonovan): ValueSpec.{Doc,Comment}? - - case *ast.BadDecl, *ast.BadExpr, *ast.BadStmt: - // nop - } - - // TODO(adonovan): opt: merge the logic of ast.Inspect() into - // the switch above so we can make interleaved callbacks for - // both Nodes and Tokens in the right order and avoid the need - // to sort. - sort.Sort(byPos(children)) - - return children -} - -type byPos []ast.Node - -func (sl byPos) Len() int { - return len(sl) -} -func (sl byPos) Less(i, j int) bool { - return sl[i].Pos() < sl[j].Pos() -} -func (sl byPos) Swap(i, j int) { - sl[i], sl[j] = sl[j], sl[i] -} - -// NodeDescription returns a description of the concrete type of n suitable -// for a user interface. -// -// TODO(adonovan): in some cases (e.g. Field, FieldList, Ident, -// StarExpr) we could be much more specific given the path to the AST -// root. Perhaps we should do that. -func NodeDescription(n ast.Node) string { - switch n := n.(type) { - case *ast.ArrayType: - return "array type" - case *ast.AssignStmt: - return "assignment" - case *ast.BadDecl: - return "bad declaration" - case *ast.BadExpr: - return "bad expression" - case *ast.BadStmt: - return "bad statement" - case *ast.BasicLit: - return "basic literal" - case *ast.BinaryExpr: - return fmt.Sprintf("binary %s operation", n.Op) - case *ast.BlockStmt: - return "block" - case *ast.BranchStmt: - switch n.Tok { - case token.BREAK: - return "break statement" - case token.CONTINUE: - return "continue statement" - case token.GOTO: - return "goto statement" - case token.FALLTHROUGH: - return "fall-through statement" - } - case *ast.CallExpr: - if len(n.Args) == 1 && !n.Ellipsis.IsValid() { - return "function call (or conversion)" - } - return "function call" - case *ast.CaseClause: - return "case clause" - case *ast.ChanType: - return "channel type" - case *ast.CommClause: - return "communication clause" - case *ast.Comment: - return "comment" - case *ast.CommentGroup: - return "comment group" - case *ast.CompositeLit: - return "composite literal" - case *ast.DeclStmt: - return NodeDescription(n.Decl) + " statement" - case *ast.DeferStmt: - return "defer statement" - case *ast.Ellipsis: - return "ellipsis" - case *ast.EmptyStmt: - return "empty statement" - case *ast.ExprStmt: - return "expression statement" - case *ast.Field: - // Can be any of these: - // struct {x, y int} -- struct field(s) - // struct {T} -- anon struct field - // interface {I} -- interface embedding - // interface {f()} -- interface method - // func (A) func(B) C -- receiver, param(s), result(s) - return "field/method/parameter" - case *ast.FieldList: - return "field/method/parameter list" - case *ast.File: - return "source file" - case *ast.ForStmt: - return "for loop" - case *ast.FuncDecl: - return "function declaration" - case *ast.FuncLit: - return "function literal" - case *ast.FuncType: - return "function type" - case *ast.GenDecl: - switch n.Tok { - case token.IMPORT: - return "import declaration" - case token.CONST: - return "constant declaration" - case token.TYPE: - return "type declaration" - case token.VAR: - return "variable declaration" - } - case *ast.GoStmt: - return "go statement" - case *ast.Ident: - return "identifier" - case *ast.IfStmt: - return "if statement" - case *ast.ImportSpec: - return "import specification" - case *ast.IncDecStmt: - if n.Tok == token.INC { - return "increment statement" - } - return "decrement statement" - case *ast.IndexExpr: - return "index expression" - case *ast.IndexListExpr: - return "index list expression" - case *ast.InterfaceType: - return "interface type" - case *ast.KeyValueExpr: - return "key/value association" - case *ast.LabeledStmt: - return "statement label" - case *ast.MapType: - return "map type" - case *ast.Package: - return "package" - case *ast.ParenExpr: - return "parenthesized " + NodeDescription(n.X) - case *ast.RangeStmt: - return "range loop" - case *ast.ReturnStmt: - return "return statement" - case *ast.SelectStmt: - return "select statement" - case *ast.SelectorExpr: - return "selector" - case *ast.SendStmt: - return "channel send" - case *ast.SliceExpr: - return "slice expression" - case *ast.StarExpr: - return "*-operation" // load/store expr or pointer type - case *ast.StructType: - return "struct type" - case *ast.SwitchStmt: - return "switch statement" - case *ast.TypeAssertExpr: - return "type assertion" - case *ast.TypeSpec: - return "type specification" - case *ast.TypeSwitchStmt: - return "type switch" - case *ast.UnaryExpr: - return fmt.Sprintf("unary %s operation", n.Op) - case *ast.ValueSpec: - return "value specification" - - } - panic(fmt.Sprintf("unexpected node type: %T", n)) -} - -func is[T any](x any) bool { - _, ok := x.(T) - return ok -} diff --git a/src/cmd/compile/internal/ssa/_gen/vendor/golang.org/x/tools/go/ast/astutil/imports.go b/src/cmd/compile/internal/ssa/_gen/vendor/golang.org/x/tools/go/ast/astutil/imports.go deleted file mode 100644 index a6b5ed0a8933eb..00000000000000 --- a/src/cmd/compile/internal/ssa/_gen/vendor/golang.org/x/tools/go/ast/astutil/imports.go +++ /dev/null @@ -1,490 +0,0 @@ -// Copyright 2013 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 astutil contains common utilities for working with the Go AST. -package astutil // import "golang.org/x/tools/go/ast/astutil" - -import ( - "fmt" - "go/ast" - "go/token" - "strconv" - "strings" -) - -// AddImport adds the import path to the file f, if absent. -func AddImport(fset *token.FileSet, f *ast.File, path string) (added bool) { - return AddNamedImport(fset, f, "", path) -} - -// AddNamedImport adds the import with the given name and path to the file f, if absent. -// If name is not empty, it is used to rename the import. -// -// For example, calling -// -// AddNamedImport(fset, f, "pathpkg", "path") -// -// adds -// -// import pathpkg "path" -func AddNamedImport(fset *token.FileSet, f *ast.File, name, path string) (added bool) { - if imports(f, name, path) { - return false - } - - newImport := &ast.ImportSpec{ - Path: &ast.BasicLit{ - Kind: token.STRING, - Value: strconv.Quote(path), - }, - } - if name != "" { - newImport.Name = &ast.Ident{Name: name} - } - - // Find an import decl to add to. - // The goal is to find an existing import - // whose import path has the longest shared - // prefix with path. - var ( - bestMatch = -1 // length of longest shared prefix - lastImport = -1 // index in f.Decls of the file's final import decl - impDecl *ast.GenDecl // import decl containing the best match - impIndex = -1 // spec index in impDecl containing the best match - - isThirdPartyPath = isThirdParty(path) - ) - for i, decl := range f.Decls { - gen, ok := decl.(*ast.GenDecl) - if ok && gen.Tok == token.IMPORT { - lastImport = i - // Do not add to import "C", to avoid disrupting the - // association with its doc comment, breaking cgo. - if declImports(gen, "C") { - continue - } - - // Match an empty import decl if that's all that is available. - if len(gen.Specs) == 0 && bestMatch == -1 { - impDecl = gen - } - - // Compute longest shared prefix with imports in this group and find best - // matched import spec. - // 1. Always prefer import spec with longest shared prefix. - // 2. While match length is 0, - // - for stdlib package: prefer first import spec. - // - for third party package: prefer first third party import spec. - // We cannot use last import spec as best match for third party package - // because grouped imports are usually placed last by goimports -local - // flag. - // See issue #19190. - seenAnyThirdParty := false - for j, spec := range gen.Specs { - impspec := spec.(*ast.ImportSpec) - p := importPath(impspec) - n := matchLen(p, path) - if n > bestMatch || (bestMatch == 0 && !seenAnyThirdParty && isThirdPartyPath) { - bestMatch = n - impDecl = gen - impIndex = j - } - seenAnyThirdParty = seenAnyThirdParty || isThirdParty(p) - } - } - } - - // If no import decl found, add one after the last import. - if impDecl == nil { - impDecl = &ast.GenDecl{ - Tok: token.IMPORT, - } - if lastImport >= 0 { - impDecl.TokPos = f.Decls[lastImport].End() - } else { - // There are no existing imports. - // Our new import, preceded by a blank line, goes after the package declaration - // and after the comment, if any, that starts on the same line as the - // package declaration. - impDecl.TokPos = f.Package - - file := fset.File(f.Package) - pkgLine := file.Line(f.Package) - for _, c := range f.Comments { - if file.Line(c.Pos()) > pkgLine { - break - } - // +2 for a blank line - impDecl.TokPos = c.End() + 2 - } - } - f.Decls = append(f.Decls, nil) - copy(f.Decls[lastImport+2:], f.Decls[lastImport+1:]) - f.Decls[lastImport+1] = impDecl - } - - // Insert new import at insertAt. - insertAt := 0 - if impIndex >= 0 { - // insert after the found import - insertAt = impIndex + 1 - } - impDecl.Specs = append(impDecl.Specs, nil) - copy(impDecl.Specs[insertAt+1:], impDecl.Specs[insertAt:]) - impDecl.Specs[insertAt] = newImport - pos := impDecl.Pos() - if insertAt > 0 { - // If there is a comment after an existing import, preserve the comment - // position by adding the new import after the comment. - if spec, ok := impDecl.Specs[insertAt-1].(*ast.ImportSpec); ok && spec.Comment != nil { - pos = spec.Comment.End() - } else { - // Assign same position as the previous import, - // so that the sorter sees it as being in the same block. - pos = impDecl.Specs[insertAt-1].Pos() - } - } - if newImport.Name != nil { - newImport.Name.NamePos = pos - } - newImport.Path.ValuePos = pos - newImport.EndPos = pos - - // Clean up parens. impDecl contains at least one spec. - if len(impDecl.Specs) == 1 { - // Remove unneeded parens. - impDecl.Lparen = token.NoPos - } else if !impDecl.Lparen.IsValid() { - // impDecl needs parens added. - impDecl.Lparen = impDecl.Specs[0].Pos() - } - - f.Imports = append(f.Imports, newImport) - - if len(f.Decls) <= 1 { - return true - } - - // Merge all the import declarations into the first one. - var first *ast.GenDecl - for i := 0; i < len(f.Decls); i++ { - decl := f.Decls[i] - gen, ok := decl.(*ast.GenDecl) - if !ok || gen.Tok != token.IMPORT || declImports(gen, "C") { - continue - } - if first == nil { - first = gen - continue // Don't touch the first one. - } - // We now know there is more than one package in this import - // declaration. Ensure that it ends up parenthesized. - first.Lparen = first.Pos() - // Move the imports of the other import declaration to the first one. - for _, spec := range gen.Specs { - spec.(*ast.ImportSpec).Path.ValuePos = first.Pos() - first.Specs = append(first.Specs, spec) - } - f.Decls = append(f.Decls[:i], f.Decls[i+1:]...) - i-- - } - - return true -} - -func isThirdParty(importPath string) bool { - // Third party package import path usually contains "." (".com", ".org", ...) - // This logic is taken from golang.org/x/tools/imports package. - return strings.Contains(importPath, ".") -} - -// DeleteImport deletes the import path from the file f, if present. -// If there are duplicate import declarations, all matching ones are deleted. -func DeleteImport(fset *token.FileSet, f *ast.File, path string) (deleted bool) { - return DeleteNamedImport(fset, f, "", path) -} - -// DeleteNamedImport deletes the import with the given name and path from the file f, if present. -// If there are duplicate import declarations, all matching ones are deleted. -func DeleteNamedImport(fset *token.FileSet, f *ast.File, name, path string) (deleted bool) { - var delspecs []*ast.ImportSpec - var delcomments []*ast.CommentGroup - - // Find the import nodes that import path, if any. - for i := 0; i < len(f.Decls); i++ { - decl := f.Decls[i] - gen, ok := decl.(*ast.GenDecl) - if !ok || gen.Tok != token.IMPORT { - continue - } - for j := 0; j < len(gen.Specs); j++ { - spec := gen.Specs[j] - impspec := spec.(*ast.ImportSpec) - if importName(impspec) != name || importPath(impspec) != path { - continue - } - - // We found an import spec that imports path. - // Delete it. - delspecs = append(delspecs, impspec) - deleted = true - copy(gen.Specs[j:], gen.Specs[j+1:]) - gen.Specs = gen.Specs[:len(gen.Specs)-1] - - // If this was the last import spec in this decl, - // delete the decl, too. - if len(gen.Specs) == 0 { - copy(f.Decls[i:], f.Decls[i+1:]) - f.Decls = f.Decls[:len(f.Decls)-1] - i-- - break - } else if len(gen.Specs) == 1 { - if impspec.Doc != nil { - delcomments = append(delcomments, impspec.Doc) - } - if impspec.Comment != nil { - delcomments = append(delcomments, impspec.Comment) - } - for _, cg := range f.Comments { - // Found comment on the same line as the import spec. - if cg.End() < impspec.Pos() && fset.Position(cg.End()).Line == fset.Position(impspec.Pos()).Line { - delcomments = append(delcomments, cg) - break - } - } - - spec := gen.Specs[0].(*ast.ImportSpec) - - // Move the documentation right after the import decl. - if spec.Doc != nil { - for fset.Position(gen.TokPos).Line+1 < fset.Position(spec.Doc.Pos()).Line { - fset.File(gen.TokPos).MergeLine(fset.Position(gen.TokPos).Line) - } - } - for _, cg := range f.Comments { - if cg.End() < spec.Pos() && fset.Position(cg.End()).Line == fset.Position(spec.Pos()).Line { - for fset.Position(gen.TokPos).Line+1 < fset.Position(spec.Pos()).Line { - fset.File(gen.TokPos).MergeLine(fset.Position(gen.TokPos).Line) - } - break - } - } - } - if j > 0 { - lastImpspec := gen.Specs[j-1].(*ast.ImportSpec) - lastLine := fset.PositionFor(lastImpspec.Path.ValuePos, false).Line - line := fset.PositionFor(impspec.Path.ValuePos, false).Line - - // We deleted an entry but now there may be - // a blank line-sized hole where the import was. - if line-lastLine > 1 || !gen.Rparen.IsValid() { - // There was a blank line immediately preceding the deleted import, - // so there's no need to close the hole. The right parenthesis is - // invalid after AddImport to an import statement without parenthesis. - // Do nothing. - } else if line != fset.File(gen.Rparen).LineCount() { - // There was no blank line. Close the hole. - fset.File(gen.Rparen).MergeLine(line) - } - } - j-- - } - } - - // Delete imports from f.Imports. - for i := 0; i < len(f.Imports); i++ { - imp := f.Imports[i] - for j, del := range delspecs { - if imp == del { - copy(f.Imports[i:], f.Imports[i+1:]) - f.Imports = f.Imports[:len(f.Imports)-1] - copy(delspecs[j:], delspecs[j+1:]) - delspecs = delspecs[:len(delspecs)-1] - i-- - break - } - } - } - - // Delete comments from f.Comments. - for i := 0; i < len(f.Comments); i++ { - cg := f.Comments[i] - for j, del := range delcomments { - if cg == del { - copy(f.Comments[i:], f.Comments[i+1:]) - f.Comments = f.Comments[:len(f.Comments)-1] - copy(delcomments[j:], delcomments[j+1:]) - delcomments = delcomments[:len(delcomments)-1] - i-- - break - } - } - } - - if len(delspecs) > 0 { - panic(fmt.Sprintf("deleted specs from Decls but not Imports: %v", delspecs)) - } - - return -} - -// RewriteImport rewrites any import of path oldPath to path newPath. -func RewriteImport(fset *token.FileSet, f *ast.File, oldPath, newPath string) (rewrote bool) { - for _, imp := range f.Imports { - if importPath(imp) == oldPath { - rewrote = true - // record old End, because the default is to compute - // it using the length of imp.Path.Value. - imp.EndPos = imp.End() - imp.Path.Value = strconv.Quote(newPath) - } - } - return -} - -// UsesImport reports whether a given import is used. -// The provided File must have been parsed with syntactic object resolution -// (not using go/parser.SkipObjectResolution). -func UsesImport(f *ast.File, path string) (used bool) { - if f.Scope == nil { - panic("file f was not parsed with syntactic object resolution") - } - spec := importSpec(f, path) - if spec == nil { - return - } - - name := spec.Name.String() - switch name { - case " ": - // If the package name is not explicitly specified, - // make an educated guess. This is not guaranteed to be correct. - lastSlash := strings.LastIndex(path, "/") - if lastSlash == -1 { - name = path - } else { - name = path[lastSlash+1:] - } - case "_", ".": - // Not sure if this import is used - err on the side of caution. - return true - } - - ast.Walk(visitFn(func(n ast.Node) { - sel, ok := n.(*ast.SelectorExpr) - if ok && isTopName(sel.X, name) { - used = true - } - }), f) - - return -} - -type visitFn func(node ast.Node) - -func (fn visitFn) Visit(node ast.Node) ast.Visitor { - fn(node) - return fn -} - -// imports reports whether f has an import with the specified name and path. -func imports(f *ast.File, name, path string) bool { - for _, s := range f.Imports { - if importName(s) == name && importPath(s) == path { - return true - } - } - return false -} - -// importSpec returns the import spec if f imports path, -// or nil otherwise. -func importSpec(f *ast.File, path string) *ast.ImportSpec { - for _, s := range f.Imports { - if importPath(s) == path { - return s - } - } - return nil -} - -// importName returns the name of s, -// or "" if the import is not named. -func importName(s *ast.ImportSpec) string { - if s.Name == nil { - return "" - } - return s.Name.Name -} - -// importPath returns the unquoted import path of s, -// or "" if the path is not properly quoted. -func importPath(s *ast.ImportSpec) string { - t, err := strconv.Unquote(s.Path.Value) - if err != nil { - return "" - } - return t -} - -// declImports reports whether gen contains an import of path. -func declImports(gen *ast.GenDecl, path string) bool { - if gen.Tok != token.IMPORT { - return false - } - for _, spec := range gen.Specs { - impspec := spec.(*ast.ImportSpec) - if importPath(impspec) == path { - return true - } - } - return false -} - -// matchLen returns the length of the longest path segment prefix shared by x and y. -func matchLen(x, y string) int { - n := 0 - for i := 0; i < len(x) && i < len(y) && x[i] == y[i]; i++ { - if x[i] == '/' { - n++ - } - } - return n -} - -// isTopName returns true if n is a top-level unresolved identifier with the given name. -func isTopName(n ast.Expr, name string) bool { - id, ok := n.(*ast.Ident) - return ok && id.Name == name && id.Obj == nil -} - -// Imports returns the file imports grouped by paragraph. -func Imports(fset *token.FileSet, f *ast.File) [][]*ast.ImportSpec { - var groups [][]*ast.ImportSpec - - for _, decl := range f.Decls { - genDecl, ok := decl.(*ast.GenDecl) - if !ok || genDecl.Tok != token.IMPORT { - break - } - - group := []*ast.ImportSpec{} - - var lastLine int - for _, spec := range genDecl.Specs { - importSpec := spec.(*ast.ImportSpec) - pos := importSpec.Path.ValuePos - line := fset.Position(pos).Line - if lastLine > 0 && pos > 0 && line-lastLine > 1 { - groups = append(groups, group) - group = []*ast.ImportSpec{} - } - group = append(group, importSpec) - lastLine = line - } - groups = append(groups, group) - } - - return groups -} diff --git a/src/cmd/compile/internal/ssa/_gen/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go b/src/cmd/compile/internal/ssa/_gen/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go deleted file mode 100644 index 58934f76633d50..00000000000000 --- a/src/cmd/compile/internal/ssa/_gen/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go +++ /dev/null @@ -1,486 +0,0 @@ -// Copyright 2017 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 astutil - -import ( - "fmt" - "go/ast" - "reflect" - "sort" -) - -// An ApplyFunc is invoked by Apply for each node n, even if n is nil, -// before and/or after the node's children, using a Cursor describing -// the current node and providing operations on it. -// -// The return value of ApplyFunc controls the syntax tree traversal. -// See Apply for details. -type ApplyFunc func(*Cursor) bool - -// Apply traverses a syntax tree recursively, starting with root, -// and calling pre and post for each node as described below. -// Apply returns the syntax tree, possibly modified. -// -// If pre is not nil, it is called for each node before the node's -// children are traversed (pre-order). If pre returns false, no -// children are traversed, and post is not called for that node. -// -// If post is not nil, and a prior call of pre didn't return false, -// post is called for each node after its children are traversed -// (post-order). If post returns false, traversal is terminated and -// Apply returns immediately. -// -// Only fields that refer to AST nodes are considered children; -// i.e., token.Pos, Scopes, Objects, and fields of basic types -// (strings, etc.) are ignored. -// -// Children are traversed in the order in which they appear in the -// respective node's struct definition. A package's files are -// traversed in the filenames' alphabetical order. -func Apply(root ast.Node, pre, post ApplyFunc) (result ast.Node) { - parent := &struct{ ast.Node }{root} - defer func() { - if r := recover(); r != nil && r != abort { - panic(r) - } - result = parent.Node - }() - a := &application{pre: pre, post: post} - a.apply(parent, "Node", nil, root) - return -} - -var abort = new(int) // singleton, to signal termination of Apply - -// A Cursor describes a node encountered during Apply. -// Information about the node and its parent is available -// from the Node, Parent, Name, and Index methods. -// -// If p is a variable of type and value of the current parent node -// c.Parent(), and f is the field identifier with name c.Name(), -// the following invariants hold: -// -// p.f == c.Node() if c.Index() < 0 -// p.f[c.Index()] == c.Node() if c.Index() >= 0 -// -// The methods Replace, Delete, InsertBefore, and InsertAfter -// can be used to change the AST without disrupting Apply. -type Cursor struct { - parent ast.Node - name string - iter *iterator // valid if non-nil - node ast.Node -} - -// Node returns the current Node. -func (c *Cursor) Node() ast.Node { return c.node } - -// Parent returns the parent of the current Node. -func (c *Cursor) Parent() ast.Node { return c.parent } - -// Name returns the name of the parent Node field that contains the current Node. -// If the parent is a *ast.Package and the current Node is a *ast.File, Name returns -// the filename for the current Node. -func (c *Cursor) Name() string { return c.name } - -// Index reports the index >= 0 of the current Node in the slice of Nodes that -// contains it, or a value < 0 if the current Node is not part of a slice. -// The index of the current node changes if InsertBefore is called while -// processing the current node. -func (c *Cursor) Index() int { - if c.iter != nil { - return c.iter.index - } - return -1 -} - -// field returns the current node's parent field value. -func (c *Cursor) field() reflect.Value { - return reflect.Indirect(reflect.ValueOf(c.parent)).FieldByName(c.name) -} - -// Replace replaces the current Node with n. -// The replacement node is not walked by Apply. -func (c *Cursor) Replace(n ast.Node) { - if _, ok := c.node.(*ast.File); ok { - file, ok := n.(*ast.File) - if !ok { - panic("attempt to replace *ast.File with non-*ast.File") - } - c.parent.(*ast.Package).Files[c.name] = file - return - } - - v := c.field() - if i := c.Index(); i >= 0 { - v = v.Index(i) - } - v.Set(reflect.ValueOf(n)) -} - -// Delete deletes the current Node from its containing slice. -// If the current Node is not part of a slice, Delete panics. -// As a special case, if the current node is a package file, -// Delete removes it from the package's Files map. -func (c *Cursor) Delete() { - if _, ok := c.node.(*ast.File); ok { - delete(c.parent.(*ast.Package).Files, c.name) - return - } - - i := c.Index() - if i < 0 { - panic("Delete node not contained in slice") - } - v := c.field() - l := v.Len() - reflect.Copy(v.Slice(i, l), v.Slice(i+1, l)) - v.Index(l - 1).Set(reflect.Zero(v.Type().Elem())) - v.SetLen(l - 1) - c.iter.step-- -} - -// InsertAfter inserts n after the current Node in its containing slice. -// If the current Node is not part of a slice, InsertAfter panics. -// Apply does not walk n. -func (c *Cursor) InsertAfter(n ast.Node) { - i := c.Index() - if i < 0 { - panic("InsertAfter node not contained in slice") - } - v := c.field() - v.Set(reflect.Append(v, reflect.Zero(v.Type().Elem()))) - l := v.Len() - reflect.Copy(v.Slice(i+2, l), v.Slice(i+1, l)) - v.Index(i + 1).Set(reflect.ValueOf(n)) - c.iter.step++ -} - -// InsertBefore inserts n before the current Node in its containing slice. -// If the current Node is not part of a slice, InsertBefore panics. -// Apply will not walk n. -func (c *Cursor) InsertBefore(n ast.Node) { - i := c.Index() - if i < 0 { - panic("InsertBefore node not contained in slice") - } - v := c.field() - v.Set(reflect.Append(v, reflect.Zero(v.Type().Elem()))) - l := v.Len() - reflect.Copy(v.Slice(i+1, l), v.Slice(i, l)) - v.Index(i).Set(reflect.ValueOf(n)) - c.iter.index++ -} - -// application carries all the shared data so we can pass it around cheaply. -type application struct { - pre, post ApplyFunc - cursor Cursor - iter iterator -} - -func (a *application) apply(parent ast.Node, name string, iter *iterator, n ast.Node) { - // convert typed nil into untyped nil - if v := reflect.ValueOf(n); v.Kind() == reflect.Ptr && v.IsNil() { - n = nil - } - - // avoid heap-allocating a new cursor for each apply call; reuse a.cursor instead - saved := a.cursor - a.cursor.parent = parent - a.cursor.name = name - a.cursor.iter = iter - a.cursor.node = n - - if a.pre != nil && !a.pre(&a.cursor) { - a.cursor = saved - return - } - - // walk children - // (the order of the cases matches the order of the corresponding node types in go/ast) - switch n := n.(type) { - case nil: - // nothing to do - - // Comments and fields - case *ast.Comment: - // nothing to do - - case *ast.CommentGroup: - if n != nil { - a.applyList(n, "List") - } - - case *ast.Field: - a.apply(n, "Doc", nil, n.Doc) - a.applyList(n, "Names") - a.apply(n, "Type", nil, n.Type) - a.apply(n, "Tag", nil, n.Tag) - a.apply(n, "Comment", nil, n.Comment) - - case *ast.FieldList: - a.applyList(n, "List") - - // Expressions - case *ast.BadExpr, *ast.Ident, *ast.BasicLit: - // nothing to do - - case *ast.Ellipsis: - a.apply(n, "Elt", nil, n.Elt) - - case *ast.FuncLit: - a.apply(n, "Type", nil, n.Type) - a.apply(n, "Body", nil, n.Body) - - case *ast.CompositeLit: - a.apply(n, "Type", nil, n.Type) - a.applyList(n, "Elts") - - case *ast.ParenExpr: - a.apply(n, "X", nil, n.X) - - case *ast.SelectorExpr: - a.apply(n, "X", nil, n.X) - a.apply(n, "Sel", nil, n.Sel) - - case *ast.IndexExpr: - a.apply(n, "X", nil, n.X) - a.apply(n, "Index", nil, n.Index) - - case *ast.IndexListExpr: - a.apply(n, "X", nil, n.X) - a.applyList(n, "Indices") - - case *ast.SliceExpr: - a.apply(n, "X", nil, n.X) - a.apply(n, "Low", nil, n.Low) - a.apply(n, "High", nil, n.High) - a.apply(n, "Max", nil, n.Max) - - case *ast.TypeAssertExpr: - a.apply(n, "X", nil, n.X) - a.apply(n, "Type", nil, n.Type) - - case *ast.CallExpr: - a.apply(n, "Fun", nil, n.Fun) - a.applyList(n, "Args") - - case *ast.StarExpr: - a.apply(n, "X", nil, n.X) - - case *ast.UnaryExpr: - a.apply(n, "X", nil, n.X) - - case *ast.BinaryExpr: - a.apply(n, "X", nil, n.X) - a.apply(n, "Y", nil, n.Y) - - case *ast.KeyValueExpr: - a.apply(n, "Key", nil, n.Key) - a.apply(n, "Value", nil, n.Value) - - // Types - case *ast.ArrayType: - a.apply(n, "Len", nil, n.Len) - a.apply(n, "Elt", nil, n.Elt) - - case *ast.StructType: - a.apply(n, "Fields", nil, n.Fields) - - case *ast.FuncType: - if tparams := n.TypeParams; tparams != nil { - a.apply(n, "TypeParams", nil, tparams) - } - a.apply(n, "Params", nil, n.Params) - a.apply(n, "Results", nil, n.Results) - - case *ast.InterfaceType: - a.apply(n, "Methods", nil, n.Methods) - - case *ast.MapType: - a.apply(n, "Key", nil, n.Key) - a.apply(n, "Value", nil, n.Value) - - case *ast.ChanType: - a.apply(n, "Value", nil, n.Value) - - // Statements - case *ast.BadStmt: - // nothing to do - - case *ast.DeclStmt: - a.apply(n, "Decl", nil, n.Decl) - - case *ast.EmptyStmt: - // nothing to do - - case *ast.LabeledStmt: - a.apply(n, "Label", nil, n.Label) - a.apply(n, "Stmt", nil, n.Stmt) - - case *ast.ExprStmt: - a.apply(n, "X", nil, n.X) - - case *ast.SendStmt: - a.apply(n, "Chan", nil, n.Chan) - a.apply(n, "Value", nil, n.Value) - - case *ast.IncDecStmt: - a.apply(n, "X", nil, n.X) - - case *ast.AssignStmt: - a.applyList(n, "Lhs") - a.applyList(n, "Rhs") - - case *ast.GoStmt: - a.apply(n, "Call", nil, n.Call) - - case *ast.DeferStmt: - a.apply(n, "Call", nil, n.Call) - - case *ast.ReturnStmt: - a.applyList(n, "Results") - - case *ast.BranchStmt: - a.apply(n, "Label", nil, n.Label) - - case *ast.BlockStmt: - a.applyList(n, "List") - - case *ast.IfStmt: - a.apply(n, "Init", nil, n.Init) - a.apply(n, "Cond", nil, n.Cond) - a.apply(n, "Body", nil, n.Body) - a.apply(n, "Else", nil, n.Else) - - case *ast.CaseClause: - a.applyList(n, "List") - a.applyList(n, "Body") - - case *ast.SwitchStmt: - a.apply(n, "Init", nil, n.Init) - a.apply(n, "Tag", nil, n.Tag) - a.apply(n, "Body", nil, n.Body) - - case *ast.TypeSwitchStmt: - a.apply(n, "Init", nil, n.Init) - a.apply(n, "Assign", nil, n.Assign) - a.apply(n, "Body", nil, n.Body) - - case *ast.CommClause: - a.apply(n, "Comm", nil, n.Comm) - a.applyList(n, "Body") - - case *ast.SelectStmt: - a.apply(n, "Body", nil, n.Body) - - case *ast.ForStmt: - a.apply(n, "Init", nil, n.Init) - a.apply(n, "Cond", nil, n.Cond) - a.apply(n, "Post", nil, n.Post) - a.apply(n, "Body", nil, n.Body) - - case *ast.RangeStmt: - a.apply(n, "Key", nil, n.Key) - a.apply(n, "Value", nil, n.Value) - a.apply(n, "X", nil, n.X) - a.apply(n, "Body", nil, n.Body) - - // Declarations - case *ast.ImportSpec: - a.apply(n, "Doc", nil, n.Doc) - a.apply(n, "Name", nil, n.Name) - a.apply(n, "Path", nil, n.Path) - a.apply(n, "Comment", nil, n.Comment) - - case *ast.ValueSpec: - a.apply(n, "Doc", nil, n.Doc) - a.applyList(n, "Names") - a.apply(n, "Type", nil, n.Type) - a.applyList(n, "Values") - a.apply(n, "Comment", nil, n.Comment) - - case *ast.TypeSpec: - a.apply(n, "Doc", nil, n.Doc) - a.apply(n, "Name", nil, n.Name) - if tparams := n.TypeParams; tparams != nil { - a.apply(n, "TypeParams", nil, tparams) - } - a.apply(n, "Type", nil, n.Type) - a.apply(n, "Comment", nil, n.Comment) - - case *ast.BadDecl: - // nothing to do - - case *ast.GenDecl: - a.apply(n, "Doc", nil, n.Doc) - a.applyList(n, "Specs") - - case *ast.FuncDecl: - a.apply(n, "Doc", nil, n.Doc) - a.apply(n, "Recv", nil, n.Recv) - a.apply(n, "Name", nil, n.Name) - a.apply(n, "Type", nil, n.Type) - a.apply(n, "Body", nil, n.Body) - - // Files and packages - case *ast.File: - a.apply(n, "Doc", nil, n.Doc) - a.apply(n, "Name", nil, n.Name) - a.applyList(n, "Decls") - // Don't walk n.Comments; they have either been walked already if - // they are Doc comments, or they can be easily walked explicitly. - - case *ast.Package: - // collect and sort names for reproducible behavior - var names []string - for name := range n.Files { - names = append(names, name) - } - sort.Strings(names) - for _, name := range names { - a.apply(n, name, nil, n.Files[name]) - } - - default: - panic(fmt.Sprintf("Apply: unexpected node type %T", n)) - } - - if a.post != nil && !a.post(&a.cursor) { - panic(abort) - } - - a.cursor = saved -} - -// An iterator controls iteration over a slice of nodes. -type iterator struct { - index, step int -} - -func (a *application) applyList(parent ast.Node, name string) { - // avoid heap-allocating a new iterator for each applyList call; reuse a.iter instead - saved := a.iter - a.iter.index = 0 - for { - // must reload parent.name each time, since cursor modifications might change it - v := reflect.Indirect(reflect.ValueOf(parent)).FieldByName(name) - if a.iter.index >= v.Len() { - break - } - - // element x may be nil in a bad AST - be cautious - var x ast.Node - if e := v.Index(a.iter.index); e.IsValid() { - x = e.Interface().(ast.Node) - } - - a.iter.step = 1 - a.apply(parent, name, &a.iter, x) - a.iter.index += a.iter.step - } - a.iter = saved -} diff --git a/src/cmd/compile/internal/ssa/_gen/vendor/golang.org/x/tools/go/ast/astutil/util.go b/src/cmd/compile/internal/ssa/_gen/vendor/golang.org/x/tools/go/ast/astutil/util.go deleted file mode 100644 index ca71e3e1055387..00000000000000 --- a/src/cmd/compile/internal/ssa/_gen/vendor/golang.org/x/tools/go/ast/astutil/util.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2015 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 astutil - -import "go/ast" - -// Unparen returns e with any enclosing parentheses stripped. -// Deprecated: use [ast.Unparen]. -func Unparen(e ast.Expr) ast.Expr { return ast.Unparen(e) } diff --git a/src/cmd/compile/internal/ssa/_gen/vendor/modules.txt b/src/cmd/compile/internal/ssa/_gen/vendor/modules.txt deleted file mode 100644 index 2efa97223356a2..00000000000000 --- a/src/cmd/compile/internal/ssa/_gen/vendor/modules.txt +++ /dev/null @@ -1,3 +0,0 @@ -# golang.org/x/tools v0.27.0 -## explicit; go 1.22.0 -golang.org/x/tools/go/ast/astutil diff --git a/src/cmd/compile/internal/ssa/allocators.go b/src/cmd/compile/internal/ssa/allocators.go index 10b1c582801db2..222ae73f2b80e0 100644 --- a/src/cmd/compile/internal/ssa/allocators.go +++ b/src/cmd/compile/internal/ssa/allocators.go @@ -31,7 +31,9 @@ func (c *Cache) allocValueSlice(n int) []*Value { return s } func (c *Cache) freeValueSlice(s []*Value) { - clear(s) + for i := range s { + s[i] = nil + } b := bits.Len(uint(cap(s)) - 1) var sp *[]*Value if len(c.hdrValueSlice) == 0 { @@ -67,7 +69,9 @@ func (c *Cache) allocLimitSlice(n int) []limit { return s } func (c *Cache) freeLimitSlice(s []limit) { - clear(s) + for i := range s { + s[i] = limit{} + } b := bits.Len(uint(cap(s)) - 1) var sp *[]limit if len(c.hdrLimitSlice) == 0 { diff --git a/src/cmd/compile/internal/ssa/block.go b/src/cmd/compile/internal/ssa/block.go index 1240bfd6556a11..0c9aea8f96844d 100644 --- a/src/cmd/compile/internal/ssa/block.go +++ b/src/cmd/compile/internal/ssa/block.go @@ -264,7 +264,10 @@ func (b *Block) resetWithControl2(kind BlockKind, v, w *Value) { // The values in b.Values after i must already have had their args reset, // to maintain correct value uses counts. func (b *Block) truncateValues(i int) { - clear(b.Values[i:]) + tail := b.Values[i:] + for j := range tail { + tail[j] = nil + } b.Values = b.Values[:i] } diff --git a/src/cmd/compile/internal/ssa/cache.go b/src/cmd/compile/internal/ssa/cache.go index 0c16efcd57d6ac..fd19cb3c0980a0 100644 --- a/src/cmd/compile/internal/ssa/cache.go +++ b/src/cmd/compile/internal/ssa/cache.go @@ -39,13 +39,24 @@ type Cache struct { func (c *Cache) Reset() { nv := sort.Search(len(c.values), func(i int) bool { return c.values[i].ID == 0 }) - clear(c.values[:nv]) + xv := c.values[:nv] + for i := range xv { + xv[i] = Value{} + } nb := sort.Search(len(c.blocks), func(i int) bool { return c.blocks[i].ID == 0 }) - clear(c.blocks[:nb]) + xb := c.blocks[:nb] + for i := range xb { + xb[i] = Block{} + } nl := sort.Search(len(c.locs), func(i int) bool { return c.locs[i] == nil }) - clear(c.locs[:nl]) + xl := c.locs[:nl] + for i := range xl { + xl[i] = nil + } // regalloc sets the length of c.regallocValues to whatever it may use, // so clear according to length. - clear(c.regallocValues) + for i := range c.regallocValues { + c.regallocValues[i] = valState{} + } } diff --git a/src/cmd/compile/internal/ssa/config.go b/src/cmd/compile/internal/ssa/config.go index d4cd32a0d7b5b6..a3131efa41c73d 100644 --- a/src/cmd/compile/internal/ssa/config.go +++ b/src/cmd/compile/internal/ssa/config.go @@ -50,14 +50,6 @@ type Config struct { haveBswap64 bool // architecture implements Bswap64 haveBswap32 bool // architecture implements Bswap32 haveBswap16 bool // architecture implements Bswap16 - - // mulRecipes[x] = function to build v * x from v. - mulRecipes map[int64]mulRecipe -} - -type mulRecipe struct { - cost int - build func(*Value, *Value) *Value // build(m, v) returns v * x built at m. } type ( @@ -372,8 +364,6 @@ func NewConfig(arch string, types Types, ctxt *obj.Link, optimize, softfloat boo opcodeTable[Op386LoweredWB].reg.clobbers |= 1 << 3 // BX } - c.buildRecipes(arch) - return c } @@ -392,253 +382,3 @@ func (c *Config) haveByteSwap(size int64) bool { return false } } - -func (c *Config) buildRecipes(arch string) { - // Information for strength-reducing multiplies. - type linearCombo struct { - // we can compute a*x+b*y in one instruction - a, b int64 - // cost, in arbitrary units (tenths of cycles, usually) - cost int - // builds SSA value for a*x+b*y. Use the position - // information from m. - build func(m, x, y *Value) *Value - } - - // List all the linear combination instructions we have. - var linearCombos []linearCombo - r := func(a, b int64, cost int, build func(m, x, y *Value) *Value) { - linearCombos = append(linearCombos, linearCombo{a: a, b: b, cost: cost, build: build}) - } - var mulCost int - switch arch { - case "amd64": - // Assumes that the following costs from https://gmplib.org/~tege/x86-timing.pdf: - // 1 - addq, shlq, leaq, negq, subq - // 3 - imulq - // These costs limit the rewrites to two instructions. - // Operations which have to happen in place (and thus - // may require a reg-reg move) score slightly higher. - mulCost = 30 - // add - r(1, 1, 10, - func(m, x, y *Value) *Value { - v := m.Block.NewValue2(m.Pos, OpAMD64ADDQ, m.Type, x, y) - if m.Type.Size() == 4 { - v.Op = OpAMD64ADDL - } - return v - }) - // neg - r(-1, 0, 11, - func(m, x, y *Value) *Value { - v := m.Block.NewValue1(m.Pos, OpAMD64NEGQ, m.Type, x) - if m.Type.Size() == 4 { - v.Op = OpAMD64NEGL - } - return v - }) - // sub - r(1, -1, 11, - func(m, x, y *Value) *Value { - v := m.Block.NewValue2(m.Pos, OpAMD64SUBQ, m.Type, x, y) - if m.Type.Size() == 4 { - v.Op = OpAMD64SUBL - } - return v - }) - // lea - r(1, 2, 10, - func(m, x, y *Value) *Value { - v := m.Block.NewValue2(m.Pos, OpAMD64LEAQ2, m.Type, x, y) - if m.Type.Size() == 4 { - v.Op = OpAMD64LEAL2 - } - return v - }) - r(1, 4, 10, - func(m, x, y *Value) *Value { - v := m.Block.NewValue2(m.Pos, OpAMD64LEAQ4, m.Type, x, y) - if m.Type.Size() == 4 { - v.Op = OpAMD64LEAL4 - } - return v - }) - r(1, 8, 10, - func(m, x, y *Value) *Value { - v := m.Block.NewValue2(m.Pos, OpAMD64LEAQ8, m.Type, x, y) - if m.Type.Size() == 4 { - v.Op = OpAMD64LEAL8 - } - return v - }) - // regular shifts - for i := 2; i < 64; i++ { - r(1< 4 { - c++ - } - r(1, 1< 4 { - c++ - } - r(-1< 4 { - c++ - } - r(1, -1< 1; n /= 2 { + if combineStores(v, n) { + continue + } + } } } } -// combineStores tries to combine the stores ending in root. -func combineStores(root *Value) { +// Try to combine the n stores ending in root. +// Returns true if successful. +func combineStores(root *Value, n int64) bool { // Helper functions. - maxRegSize := root.Block.Func.Config.RegSize type StoreRecord struct { store *Value offset int64 - size int64 } getShiftBase := func(a []StoreRecord) *Value { x := a[0].store.Args[1] @@ -471,122 +474,86 @@ func combineStores(root *Value) { return val.AuxInt } + // Element size of the individual stores. + size := root.Aux.(*types.Type).Size() + if size*n > root.Block.Func.Config.RegSize { + return false + } + // Gather n stores to look at. Check easy conditions we require. - allMergeable := make([]StoreRecord, 0, 8) + a := make([]StoreRecord, 0, 8) rbase, roff := splitPtr(root.Args[0]) if root.Block.Func.Config.arch == "S390X" { // s390x can't handle unaligned accesses to global variables. if rbase.ptr.Op == OpAddr { - return + return false } } - allMergeable = append(allMergeable, StoreRecord{root, roff, root.Aux.(*types.Type).Size()}) - allMergeableSize := root.Aux.(*types.Type).Size() - // TODO: this loop strictly requires stores to chain together in memory. - // maybe we can break this constraint and match more patterns. - for i, x := 1, root.Args[2]; i < 8; i, x = i+1, x.Args[2] { + a = append(a, StoreRecord{root, roff}) + for i, x := int64(1), root.Args[2]; i < n; i, x = i+1, x.Args[2] { if x.Op != OpStore { - break + return false } if x.Block != root.Block { - break + return false } if x.Uses != 1 { // Note: root can have more than one use. - break - } - xSize := x.Aux.(*types.Type).Size() - if xSize == 0 { - break + return false } - if xSize > maxRegSize-allMergeableSize { - break + if x.Aux.(*types.Type).Size() != size { + // TODO: the constant source and consecutive load source cases + // do not need all the stores to be the same size. + return false } base, off := splitPtr(x.Args[0]) if base != rbase { - break - } - allMergeable = append(allMergeable, StoreRecord{x, off, xSize}) - allMergeableSize += xSize - } - if len(allMergeable) <= 1 { - return - } - // Fit the combined total size to be one of the register size. - mergeableSet := map[int64][]StoreRecord{} - for i, size := 0, int64(0); i < len(allMergeable); i++ { - size += allMergeable[i].size - for _, bucketSize := range []int64{8, 4, 2} { - if size == bucketSize { - mergeableSet[size] = slices.Clone(allMergeable[:i+1]) - break - } + return false } + a = append(a, StoreRecord{x, off}) } - var a []StoreRecord - var aTotalSize int64 - var mem *Value - var pos src.XPos - // Pick the largest mergeable set. - for _, s := range []int64{8, 4, 2} { - candidate := mergeableSet[s] - // TODO: a refactoring might be more efficient: - // Find a bunch of stores that are all adjacent and then decide how big a chunk of - // those sequential stores to combine. - if len(candidate) >= 2 { - // Before we sort, grab the memory arg the result should have. - mem = candidate[len(candidate)-1].store.Args[2] - // Also grab position of first store (last in array = first in memory order). - pos = candidate[len(candidate)-1].store.Pos - // Sort stores in increasing address order. - slices.SortFunc(candidate, func(sr1, sr2 StoreRecord) int { - return cmp.Compare(sr1.offset, sr2.offset) - }) - // Check that everything is written to sequential locations. - sequential := true - for i := 1; i < len(candidate); i++ { - if candidate[i].offset != candidate[i-1].offset+candidate[i-1].size { - sequential = false - break - } - } - if sequential { - a = candidate - aTotalSize = s - break - } + // Before we sort, grab the memory arg the result should have. + mem := a[n-1].store.Args[2] + // Also grab position of first store (last in array = first in memory order). + pos := a[n-1].store.Pos + + // Sort stores in increasing address order. + slices.SortFunc(a, func(sr1, sr2 StoreRecord) int { + return cmp.Compare(sr1.offset, sr2.offset) + }) + + // Check that everything is written to sequential locations. + for i := int64(0); i < n; i++ { + if a[i].offset != a[0].offset+i*size { + return false } } - if len(a) <= 1 { - return - } + // Memory location we're going to write at (the lowest one). ptr := a[0].store.Args[0] // Check for constant stores isConst := true - for i := range a { + for i := int64(0); i < n; i++ { switch a[i].store.Args[1].Op { case OpConst32, OpConst16, OpConst8, OpConstBool: default: isConst = false - } - if !isConst { break } } if isConst { // Modify root to do all the stores. var c int64 - for i := range a { - mask := int64(1)<<(8*a[i].size) - 1 - s := 8 * (a[i].offset - a[0].offset) + mask := int64(1)<<(8*size) - 1 + for i := int64(0); i < n; i++ { + s := 8 * size * int64(i) if root.Block.Func.Config.BigEndian { - s = (aTotalSize-a[i].size)*8 - s + s = 8*size*(n-1) - s } c |= (a[i].store.Args[1].AuxInt & mask) << s } var cv *Value - switch aTotalSize { + switch size * n { case 2: cv = root.Block.Func.ConstInt16(types.Types[types.TUINT16], int16(c)) case 4: @@ -596,7 +563,7 @@ func combineStores(root *Value) { } // Move all the stores to the root. - for i := range a { + for i := int64(0); i < n; i++ { v := a[i].store if v == root { v.Aux = cv.Type // widen store type @@ -609,14 +576,14 @@ func combineStores(root *Value) { v.Type = types.Types[types.TBOOL] // erase memory type } } - return + return true } // Check for consecutive loads as the source of the stores. var loadMem *Value var loadBase BaseAddress var loadIdx int64 - for i := range a { + for i := int64(0); i < n; i++ { load := a[i].store.Args[1] if load.Op != OpLoad { loadMem = nil @@ -655,7 +622,7 @@ func combineStores(root *Value) { if loadMem != nil { // Modify the first load to do a larger load instead. load := a[0].store.Args[1] - switch aTotalSize { + switch size * n { case 2: load.Type = types.Types[types.TUINT16] case 4: @@ -665,7 +632,7 @@ func combineStores(root *Value) { } // Modify root to do the store. - for i := range a { + for i := int64(0); i < n; i++ { v := a[i].store if v == root { v.Aux = load.Type // widen store type @@ -678,47 +645,45 @@ func combineStores(root *Value) { v.Type = types.Types[types.TBOOL] // erase memory type } } - return + return true } // Check that all the shift/trunc are of the same base value. shiftBase := getShiftBase(a) if shiftBase == nil { - return + return false } - for i := range a { + for i := int64(0); i < n; i++ { if !isShiftBase(a[i].store, shiftBase) { - return + return false } } // Check for writes in little-endian or big-endian order. isLittleEndian := true shift0 := shift(a[0].store, shiftBase) - for i := 1; i < len(a); i++ { - if shift(a[i].store, shiftBase) != shift0+(a[i].offset-a[0].offset)*8 { + for i := int64(1); i < n; i++ { + if shift(a[i].store, shiftBase) != shift0+i*size*8 { isLittleEndian = false break } } isBigEndian := true - shiftedSize := int64(0) - for i := 1; i < len(a); i++ { - shiftedSize += a[i].size - if shift(a[i].store, shiftBase) != shift0-shiftedSize*8 { + for i := int64(1); i < n; i++ { + if shift(a[i].store, shiftBase) != shift0-i*size*8 { isBigEndian = false break } } if !isLittleEndian && !isBigEndian { - return + return false } // Check to see if we need byte swap before storing. needSwap := isLittleEndian && root.Block.Func.Config.BigEndian || isBigEndian && !root.Block.Func.Config.BigEndian - if needSwap && (int64(len(a)) != aTotalSize || !root.Block.Func.Config.haveByteSwap(aTotalSize)) { - return + if needSwap && (size != 1 || !root.Block.Func.Config.haveByteSwap(n)) { + return false } // This is the commit point. @@ -728,19 +693,18 @@ func combineStores(root *Value) { if isLittleEndian && shift0 != 0 { sv = rightShift(root.Block, root.Pos, sv, shift0) } - shiftedSize = int64(aTotalSize - a[0].size) - if isBigEndian && shift0-shiftedSize*8 != 0 { - sv = rightShift(root.Block, root.Pos, sv, shift0-shiftedSize*8) + if isBigEndian && shift0-(n-1)*size*8 != 0 { + sv = rightShift(root.Block, root.Pos, sv, shift0-(n-1)*size*8) } - if sv.Type.Size() > aTotalSize { - sv = truncate(root.Block, root.Pos, sv, sv.Type.Size(), aTotalSize) + if sv.Type.Size() > size*n { + sv = truncate(root.Block, root.Pos, sv, sv.Type.Size(), size*n) } if needSwap { sv = byteSwap(root.Block, root.Pos, sv) } // Move all the stores to the root. - for i := range a { + for i := int64(0); i < n; i++ { v := a[i].store if v == root { v.Aux = sv.Type // widen store type @@ -753,6 +717,7 @@ func combineStores(root *Value) { v.Type = types.Types[types.TBOOL] // erase memory type } } + return true } func sizeType(size int64) *types.Type { diff --git a/src/cmd/compile/internal/ssa/nilcheck.go b/src/cmd/compile/internal/ssa/nilcheck.go index 9d43ec19919825..c69cd8c32ed394 100644 --- a/src/cmd/compile/internal/ssa/nilcheck.go +++ b/src/cmd/compile/internal/ssa/nilcheck.go @@ -217,12 +217,12 @@ func nilcheckelim2(f *Func) { f.Warnl(v.Pos, "removed nil check") } // For bug 33724, policy is that we might choose to bump an existing position - // off the faulting load in favor of the one from the nil check. + // off the faulting load/store in favor of the one from the nil check. // Iteration order means that first nilcheck in the chain wins, others // are bumped into the ordinary statement preservation algorithm. u := b.Values[unnecessary.get(v.Args[0].ID)] - if !u.Type.IsMemory() && !u.Pos.SameFileAndLine(v.Pos) { + if !u.Pos.SameFileAndLine(v.Pos) { if u.Pos.IsStmt() == src.PosIsStmt { pendingLines.add(u.Pos) } diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 5d13f81841482d..de6ccf25f2f26e 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -659,8 +659,6 @@ const ( OpAMD64DIVLU OpAMD64DIVWU OpAMD64NEGLflags - OpAMD64ADDQconstflags - OpAMD64ADDLconstflags OpAMD64ADDQcarry OpAMD64ADCQ OpAMD64ADDQconstcarry @@ -1810,8 +1808,6 @@ const ( OpLOONG64XORconst OpLOONG64NOR OpLOONG64NORconst - OpLOONG64ANDN - OpLOONG64ORN OpLOONG64FMADDF OpLOONG64FMADDD OpLOONG64FMSUBF @@ -1964,8 +1960,6 @@ const ( OpLOONG64LoweredPanicBoundsA OpLOONG64LoweredPanicBoundsB OpLOONG64LoweredPanicBoundsC - OpLOONG64PRELD - OpLOONG64PRELDX OpMIPSADD OpMIPSADDconst @@ -2076,7 +2070,6 @@ const ( OpMIPSLoweredGetCallerSP OpMIPSLoweredGetCallerPC OpMIPSLoweredWB - OpMIPSLoweredPubBarrier OpMIPSLoweredPanicBoundsA OpMIPSLoweredPanicBoundsB OpMIPSLoweredPanicBoundsC @@ -2208,7 +2201,6 @@ const ( OpMIPS64LoweredGetCallerSP OpMIPS64LoweredGetCallerPC OpMIPS64LoweredWB - OpMIPS64LoweredPubBarrier OpMIPS64LoweredPanicBoundsA OpMIPS64LoweredPanicBoundsB OpMIPS64LoweredPanicBoundsC @@ -2522,15 +2514,12 @@ const ( OpRISCV64ANDI OpRISCV64CLZ OpRISCV64CLZW - OpRISCV64CPOP - OpRISCV64CPOPW OpRISCV64CTZ OpRISCV64CTZW OpRISCV64NOT OpRISCV64OR OpRISCV64ORN OpRISCV64ORI - OpRISCV64REV8 OpRISCV64ROL OpRISCV64ROLW OpRISCV64ROR @@ -7955,38 +7944,6 @@ var opcodeTable = [...]opInfo{ }, }, }, - { - name: "ADDQconstflags", - auxType: auxInt32, - argLen: 1, - resultInArg0: true, - asm: x86.AADDQ, - reg: regInfo{ - inputs: []inputInfo{ - {0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15 - }, - outputs: []outputInfo{ - {1, 0}, - {0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15 - }, - }, - }, - { - name: "ADDLconstflags", - auxType: auxInt32, - argLen: 1, - resultInArg0: true, - asm: x86.AADDL, - reg: regInfo{ - inputs: []inputInfo{ - {0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15 - }, - outputs: []outputInfo{ - {1, 0}, - {0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15 - }, - }, - }, { name: "ADDQcarry", argLen: 2, @@ -13874,10 +13831,11 @@ var opcodeTable = [...]opInfo{ }, }, { - name: "DUFFZERO", - auxType: auxInt64, - argLen: 2, - unsafePoint: true, + name: "DUFFZERO", + auxType: auxInt64, + argLen: 2, + faultOnNilArg0: true, + unsafePoint: true, reg: regInfo{ inputs: []inputInfo{ {0, 128}, // DI @@ -13947,11 +13905,13 @@ var opcodeTable = [...]opInfo{ }, }, { - name: "DUFFCOPY", - auxType: auxInt64, - argLen: 3, - clobberFlags: true, - unsafePoint: true, + name: "DUFFCOPY", + auxType: auxInt64, + argLen: 3, + clobberFlags: true, + faultOnNilArg0: true, + faultOnNilArg1: true, + unsafePoint: true, reg: regInfo{ inputs: []inputInfo{ {0, 128}, // DI @@ -23036,10 +22996,11 @@ var opcodeTable = [...]opInfo{ }, }, { - name: "DUFFZERO", - auxType: auxInt64, - argLen: 2, - unsafePoint: true, + name: "DUFFZERO", + auxType: auxInt64, + argLen: 2, + faultOnNilArg0: true, + unsafePoint: true, reg: regInfo{ inputs: []inputInfo{ {0, 524288}, // R20 @@ -23061,10 +23022,12 @@ var opcodeTable = [...]opInfo{ }, }, { - name: "DUFFCOPY", - auxType: auxInt64, - argLen: 3, - unsafePoint: true, + name: "DUFFCOPY", + auxType: auxInt64, + argLen: 3, + faultOnNilArg0: true, + faultOnNilArg1: true, + unsafePoint: true, reg: regInfo{ inputs: []inputInfo{ {0, 1048576}, // R21 @@ -24377,34 +24340,6 @@ var opcodeTable = [...]opInfo{ }, }, }, - { - name: "ANDN", - argLen: 2, - asm: loong64.AANDN, - reg: regInfo{ - inputs: []inputInfo{ - {0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31 - {1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31 - }, - outputs: []outputInfo{ - {0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31 - }, - }, - }, - { - name: "ORN", - argLen: 2, - asm: loong64.AORN, - reg: regInfo{ - inputs: []inputInfo{ - {0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31 - {1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31 - }, - outputs: []outputInfo{ - {0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31 - }, - }, - }, { name: "FMADDF", argLen: 3, @@ -26480,30 +26415,6 @@ var opcodeTable = [...]opInfo{ }, }, }, - { - name: "PRELD", - auxType: auxInt64, - argLen: 2, - hasSideEffects: true, - asm: loong64.APRELD, - reg: regInfo{ - inputs: []inputInfo{ - {0, 1073741820}, // SP R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31 - }, - }, - }, - { - name: "PRELDX", - auxType: auxInt64, - argLen: 2, - hasSideEffects: true, - asm: loong64.APRELDX, - reg: regInfo{ - inputs: []inputInfo{ - {0, 1073741820}, // SP R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31 - }, - }, - }, { name: "ADD", @@ -27985,13 +27896,6 @@ var opcodeTable = [...]opInfo{ }, }, }, - { - name: "LoweredPubBarrier", - argLen: 1, - hasSideEffects: true, - asm: mips.ASYNC, - reg: regInfo{}, - }, { name: "LoweredPanicBoundsA", auxType: auxInt64, @@ -29758,13 +29662,6 @@ var opcodeTable = [...]opInfo{ }, }, }, - { - name: "LoweredPubBarrier", - argLen: 1, - hasSideEffects: true, - asm: mips.ASYNC, - reg: regInfo{}, - }, { name: "LoweredPanicBoundsA", auxType: auxInt64, @@ -33989,32 +33886,6 @@ var opcodeTable = [...]opInfo{ }, }, }, - { - name: "CPOP", - argLen: 1, - asm: riscv.ACPOP, - reg: regInfo{ - inputs: []inputInfo{ - {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - }, - outputs: []outputInfo{ - {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - }, - }, - }, - { - name: "CPOPW", - argLen: 1, - asm: riscv.ACPOPW, - reg: regInfo{ - inputs: []inputInfo{ - {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - }, - outputs: []outputInfo{ - {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - }, - }, - }, { name: "CTZ", argLen: 1, @@ -34097,19 +33968,6 @@ var opcodeTable = [...]opInfo{ }, }, }, - { - name: "REV8", - argLen: 1, - asm: riscv.AREV8, - reg: regInfo{ - inputs: []inputInfo{ - {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - }, - outputs: []outputInfo{ - {0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 - }, - }, - }, { name: "ROL", argLen: 2, diff --git a/src/cmd/compile/internal/ssa/phiopt.go b/src/cmd/compile/internal/ssa/phiopt.go index 034ee4c661046b..037845eacf2db6 100644 --- a/src/cmd/compile/internal/ssa/phiopt.go +++ b/src/cmd/compile/internal/ssa/phiopt.go @@ -119,33 +119,6 @@ func phiopt(f *Func) { continue } } - // Replaces - // if a { x = value } else { x = a } with x = a && value. - // Requires that value dominates x. - if v.Args[1-reverse] == b0.Controls[0] { - if tmp := v.Args[reverse]; sdom.IsAncestorEq(tmp.Block, b) { - v.reset(OpAndB) - v.SetArgs2(b0.Controls[0], tmp) - if f.pass.debug > 0 { - f.Warnl(b.Pos, "converted OpPhi to %v", v.Op) - } - continue - } - } - - // Replaces - // if a { x = a } else { x = value } with x = a || value. - // Requires that value dominates x. - if v.Args[reverse] == b0.Controls[0] { - if tmp := v.Args[1-reverse]; sdom.IsAncestorEq(tmp.Block, b) { - v.reset(OpOrB) - v.SetArgs2(b0.Controls[0], tmp) - if f.pass.debug > 0 { - f.Warnl(b.Pos, "converted OpPhi to %v", v.Op) - } - continue - } - } } } // strengthen phi optimization. diff --git a/src/cmd/compile/internal/ssa/poset.go b/src/cmd/compile/internal/ssa/poset.go index f4f75fbe09d8c7..b7859166f48a98 100644 --- a/src/cmd/compile/internal/ssa/poset.go +++ b/src/cmd/compile/internal/ssa/poset.go @@ -23,7 +23,9 @@ func newBitset(n int) bitset { } func (bs bitset) Reset() { - clear(bs) + for i := range bs { + bs[i] = 0 + } } func (bs bitset) Set(idx uint32) { diff --git a/src/cmd/compile/internal/ssa/prove.go b/src/cmd/compile/internal/ssa/prove.go index 5617edb21f15ed..94f23a84aa0dbd 100644 --- a/src/cmd/compile/internal/ssa/prove.go +++ b/src/cmd/compile/internal/ssa/prove.go @@ -1757,9 +1757,7 @@ func (ft *factsTable) flowLimit(v *Value) bool { case OpSub64, OpSub32, OpSub16, OpSub8: a := ft.limits[v.Args[0].ID] b := ft.limits[v.Args[1].ID] - sub := ft.newLimit(v, a.sub(b, uint(v.Type.Size())*8)) - mod := ft.detectSignedMod(v) - return sub || mod + return ft.newLimit(v, a.sub(b, uint(v.Type.Size())*8)) case OpNeg64, OpNeg32, OpNeg16, OpNeg8: a := ft.limits[v.Args[0].ID] bitsize := uint(v.Type.Size()) * 8 @@ -1915,122 +1913,6 @@ func (ft *factsTable) flowLimit(v *Value) bool { return false } -// See if we can get any facts because v is the result of signed mod by a constant. -// The mod operation has already been rewritten, so we have to try and reconstruct it. -// x % d -// is rewritten as -// x - (x / d) * d -// furthermore, the divide itself gets rewritten. If d is a power of 2 (d == 1< > k) << k -// = (x + adj) & (-1< >(w-1))>>>(w-k)) & (-1< > = signed shift, >>> = unsigned shift). - // See ./_gen/generic.rules, search for "Signed divide by power of 2". - - var w int64 - var addOp, andOp, constOp, sshiftOp, ushiftOp Op - switch v.Op { - case OpSub64: - w = 64 - addOp = OpAdd64 - andOp = OpAnd64 - constOp = OpConst64 - sshiftOp = OpRsh64x64 - ushiftOp = OpRsh64Ux64 - case OpSub32: - w = 32 - addOp = OpAdd32 - andOp = OpAnd32 - constOp = OpConst32 - sshiftOp = OpRsh32x64 - ushiftOp = OpRsh32Ux64 - case OpSub16: - w = 16 - addOp = OpAdd16 - andOp = OpAnd16 - constOp = OpConst16 - sshiftOp = OpRsh16x64 - ushiftOp = OpRsh16Ux64 - case OpSub8: - w = 8 - addOp = OpAdd8 - andOp = OpAnd8 - constOp = OpConst8 - sshiftOp = OpRsh8x64 - ushiftOp = OpRsh8Ux64 - default: - return false - } - - x := v.Args[0] - and := v.Args[1] - if and.Op != andOp { - return false - } - var add, mask *Value - if and.Args[0].Op == addOp && and.Args[1].Op == constOp { - add = and.Args[0] - mask = and.Args[1] - } else if and.Args[1].Op == addOp && and.Args[0].Op == constOp { - add = and.Args[1] - mask = and.Args[0] - } else { - return false - } - var ushift *Value - if add.Args[0] == x { - ushift = add.Args[1] - } else if add.Args[1] == x { - ushift = add.Args[0] - } else { - return false - } - if ushift.Op != ushiftOp { - return false - } - if ushift.Args[1].Op != OpConst64 { - return false - } - k := w - ushift.Args[1].AuxInt // Now we know k! - d := int64(1) << k // divisor - sshift := ushift.Args[0] - if sshift.Op != sshiftOp { - return false - } - if sshift.Args[0] != x { - return false - } - if sshift.Args[1].Op != OpConst64 || sshift.Args[1].AuxInt != w-1 { - return false - } - if mask.AuxInt != -d { - return false - } - - // All looks ok. x % d is at most +/- d-1. - return ft.signedMinMax(v, -d+1, d-1) -} - // getBranch returns the range restrictions added by p // when reaching b. p is the immediate dominator of b. func getBranch(sdom SparseTree, p *Block, b *Block) branch { diff --git a/src/cmd/compile/internal/ssa/regalloc.go b/src/cmd/compile/internal/ssa/regalloc.go index f1e210fe9b8b08..f52dad8a5d2fce 100644 --- a/src/cmd/compile/internal/ssa/regalloc.go +++ b/src/cmd/compile/internal/ssa/regalloc.go @@ -1301,7 +1301,9 @@ func (s *regAllocState) regalloc(f *Func) { dinfo = make([]dentry, l) } else { dinfo = dinfo[:l] - clear(dinfo) + for i := range dinfo { + dinfo[i] = dentry{} + } } // Load static desired register info at the end of the block. @@ -1899,10 +1901,6 @@ func (s *regAllocState) regalloc(f *Func) { if s.f.Config.hasGReg && s.regs[s.GReg].v != nil { s.freeReg(s.GReg) // Spill value in G register before any merge. } - if s.blockOrder[b.ID] > s.blockOrder[b.Succs[0].b.ID] { - // No point if we've already regalloc'd the destination. - goto badloop - } // For this to be worthwhile, the loop must have no calls in it. top := b.Succs[0].b loop := s.loopnest.b2l[top.ID] diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go index eb2c3b31b8c998..ed79d5154631ae 100644 --- a/src/cmd/compile/internal/ssa/rewrite.go +++ b/src/cmd/compile/internal/ssa/rewrite.go @@ -286,18 +286,7 @@ func canMergeLoadClobber(target, load, x *Value) bool { // approximate x dying with: // 1) target is x's only use. // 2) target is not in a deeper loop than x. - switch { - case x.Uses == 2 && x.Op == OpPhi && len(x.Args) == 2 && (x.Args[0] == target || x.Args[1] == target) && target.Uses == 1: - // This is a simple detector to determine that x is probably - // not live after target. (It does not need to be perfect, - // regalloc will issue a reg-reg move to save it if we are wrong.) - // We have: - // x = Phi(?, target) - // target = Op(load, x) - // Because target has only one use as a Phi argument, we can schedule it - // very late. Hopefully, later than the other use of x. (The other use died - // between x and target, or exists on another branch entirely). - case x.Uses > 1: + if x.Uses != 1 { return false } loopnest := x.Block.Func.loopnest() @@ -535,11 +524,6 @@ func isU8Bit(n int64) bool { return n == int64(uint8(n)) } -// is12Bit reports whether n can be represented as a signed 12 bit integer. -func is12Bit(n int64) bool { - return -(1<<11) <= n && n < (1<<11) -} - // isU12Bit reports whether n can be represented as an unsigned 12 bit integer. func isU12Bit(n int64) bool { return 0 <= n && n < (1<<12) @@ -576,30 +560,6 @@ func b2i32(b bool) int32 { return 0 } -func canMulStrengthReduce(config *Config, x int64) bool { - _, ok := config.mulRecipes[x] - return ok -} -func canMulStrengthReduce32(config *Config, x int32) bool { - _, ok := config.mulRecipes[int64(x)] - return ok -} - -// mulStrengthReduce returns v*x evaluated at the location -// (block and source position) of m. -// canMulStrengthReduce must have returned true. -func mulStrengthReduce(m *Value, v *Value, x int64) *Value { - return v.Block.Func.Config.mulRecipes[x].build(m, v) -} - -// mulStrengthReduce32 returns v*x evaluated at the location -// (block and source position) of m. -// canMulStrengthReduce32 must have returned true. -// The upper 32 bits of m might be set to junk. -func mulStrengthReduce32(m *Value, v *Value, x int32) *Value { - return v.Block.Func.Config.mulRecipes[int64(x)].build(m, v) -} - // shiftIsBounded reports whether (left/right) shift Value v is known to be bounded. // A shift is bounded if it is shifting by less than the width of the shifted value. func shiftIsBounded(v *Value) bool { @@ -1501,9 +1461,7 @@ func isInlinableMemmove(dst, src *Value, sz int64, c *Config) bool { switch c.arch { case "amd64": return sz <= 16 || (sz < 1024 && disjoint(dst, sz, src, sz)) - case "arm64": - return sz <= 64 || (sz <= 1024 && disjoint(dst, sz, src, sz)) - case "386": + case "386", "arm64": return sz <= 8 case "s390x", "ppc64", "ppc64le": return sz <= 8 || disjoint(dst, sz, src, sz) @@ -1583,11 +1541,6 @@ func GetPPC64Shiftme(auxint int64) int64 { // operation. Masks can also extend from the msb and wrap to // the lsb too. That is, the valid masks are 32 bit strings // of the form: 0..01..10..0 or 1..10..01..1 or 1...1 -// -// Note: This ignores the upper 32 bits of the input. When a -// zero extended result is desired (e.g a 64 bit result), the -// user must verify the upper 32 bits are 0 and the mask is -// contiguous (that is, non-wrapping). func isPPC64WordRotateMask(v64 int64) bool { // Isolate rightmost 1 (if none 0) and add. v := uint32(v64) @@ -1598,16 +1551,6 @@ func isPPC64WordRotateMask(v64 int64) bool { return (v&vp == 0 || vn&vpn == 0) && v != 0 } -// Test if this mask is a valid, contiguous bitmask which can be -// represented by a RLWNM mask and also clears the upper 32 bits -// of the register. -func isPPC64WordRotateMaskNonWrapping(v64 int64) bool { - // Isolate rightmost 1 (if none 0) and add. - v := uint32(v64) - vp := (v & -v) + v - return (v&vp == 0) && v != 0 && uint64(uint32(v64)) == uint64(v64) -} - // Compress mask and shift into single value of the form // me | mb<<8 | rotate<<16 | nbits<<24 where me and mb can // be used to regenerate the input mask. @@ -1717,7 +1660,7 @@ func mergePPC64AndSrdi(m, s int64) int64 { if rv&uint64(mask) != 0 { return 0 } - if !isPPC64WordRotateMaskNonWrapping(mask) { + if !isPPC64WordRotateMask(mask) { return 0 } return encodePPC64RotateMask((32-s)&31, mask, 32) @@ -1732,7 +1675,7 @@ func mergePPC64AndSldi(m, s int64) int64 { if rv&uint64(mask) != 0 { return 0 } - if !isPPC64WordRotateMaskNonWrapping(mask) { + if !isPPC64WordRotateMask(mask) { return 0 } return encodePPC64RotateMask(s&31, mask, 32) @@ -2641,33 +2584,3 @@ func bitsAdd64(x, y, carry int64) (r struct{ sum, carry int64 }) { r.sum, r.carry = int64(s), int64(c) return } - -func bitsMulU64(x, y int64) (r struct{ hi, lo int64 }) { - hi, lo := bits.Mul64(uint64(x), uint64(y)) - r.hi, r.lo = int64(hi), int64(lo) - return -} -func bitsMulU32(x, y int32) (r struct{ hi, lo int32 }) { - hi, lo := bits.Mul32(uint32(x), uint32(y)) - r.hi, r.lo = int32(hi), int32(lo) - return -} - -// flagify rewrites v which is (X ...) to (Select0 (Xflags ...)). -func flagify(v *Value) bool { - var flagVersion Op - switch v.Op { - case OpAMD64ADDQconst: - flagVersion = OpAMD64ADDQconstflags - case OpAMD64ADDLconst: - flagVersion = OpAMD64ADDLconstflags - default: - base.Fatalf("can't flagify op %s", v.Op) - } - inner := v.copyInto(v.Block) - inner.Op = flagVersion - inner.Type = types.NewTuple(v.Type, types.TypeFlags) - v.reset(OpSelect0) - v.AddArg(inner) - return true -} diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index 3d7af5f365a116..be9ed7f6e16f41 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -8556,20 +8556,18 @@ func rewriteValueAMD64_OpAMD64LEAL1(v *Value) bool { } break } - // match: (LEAL1 [c] {s} x z:(ADDL y y)) - // cond: x != z + // match: (LEAL1 [c] {s} x (ADDL y y)) // result: (LEAL2 [c] {s} x y) for { c := auxIntToInt32(v.AuxInt) s := auxToSym(v.Aux) for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { x := v_0 - z := v_1 - if z.Op != OpAMD64ADDL { + if v_1.Op != OpAMD64ADDL { continue } - y := z.Args[1] - if y != z.Args[0] || !(x != z) { + y := v_1.Args[1] + if y != v_1.Args[0] { continue } v.reset(OpAMD64LEAL2) @@ -8665,19 +8663,17 @@ func rewriteValueAMD64_OpAMD64LEAL2(v *Value) bool { v.AddArg2(x, y) return true } - // match: (LEAL2 [c] {s} x z:(ADDL y y)) - // cond: x != z + // match: (LEAL2 [c] {s} x (ADDL y y)) // result: (LEAL4 [c] {s} x y) for { c := auxIntToInt32(v.AuxInt) s := auxToSym(v.Aux) x := v_0 - z := v_1 - if z.Op != OpAMD64ADDL { + if v_1.Op != OpAMD64ADDL { break } - y := z.Args[1] - if y != z.Args[0] || !(x != z) { + y := v_1.Args[1] + if y != v_1.Args[0] { break } v.reset(OpAMD64LEAL4) @@ -8769,19 +8765,17 @@ func rewriteValueAMD64_OpAMD64LEAL4(v *Value) bool { v.AddArg2(x, y) return true } - // match: (LEAL4 [c] {s} x z:(ADDL y y)) - // cond: x != z + // match: (LEAL4 [c] {s} x (ADDL y y)) // result: (LEAL8 [c] {s} x y) for { c := auxIntToInt32(v.AuxInt) s := auxToSym(v.Aux) x := v_0 - z := v_1 - if z.Op != OpAMD64ADDL { + if v_1.Op != OpAMD64ADDL { break } - y := z.Args[1] - if y != z.Args[0] || !(x != z) { + y := v_1.Args[1] + if y != v_1.Args[0] { break } v.reset(OpAMD64LEAL8) @@ -9025,20 +9019,18 @@ func rewriteValueAMD64_OpAMD64LEAQ1(v *Value) bool { } break } - // match: (LEAQ1 [c] {s} x z:(ADDQ y y)) - // cond: x != z + // match: (LEAQ1 [c] {s} x (ADDQ y y)) // result: (LEAQ2 [c] {s} x y) for { c := auxIntToInt32(v.AuxInt) s := auxToSym(v.Aux) for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { x := v_0 - z := v_1 - if z.Op != OpAMD64ADDQ { + if v_1.Op != OpAMD64ADDQ { continue } - y := z.Args[1] - if y != z.Args[0] || !(x != z) { + y := v_1.Args[1] + if y != v_1.Args[0] { continue } v.reset(OpAMD64LEAQ2) @@ -9233,19 +9225,17 @@ func rewriteValueAMD64_OpAMD64LEAQ2(v *Value) bool { v.AddArg2(x, y) return true } - // match: (LEAQ2 [c] {s} x z:(ADDQ y y)) - // cond: x != z + // match: (LEAQ2 [c] {s} x (ADDQ y y)) // result: (LEAQ4 [c] {s} x y) for { c := auxIntToInt32(v.AuxInt) s := auxToSym(v.Aux) x := v_0 - z := v_1 - if z.Op != OpAMD64ADDQ { + if v_1.Op != OpAMD64ADDQ { break } - y := z.Args[1] - if y != z.Args[0] || !(x != z) { + y := v_1.Args[1] + if y != v_1.Args[0] { break } v.reset(OpAMD64LEAQ4) @@ -9421,19 +9411,17 @@ func rewriteValueAMD64_OpAMD64LEAQ4(v *Value) bool { v.AddArg2(x, y) return true } - // match: (LEAQ4 [c] {s} x z:(ADDQ y y)) - // cond: x != z + // match: (LEAQ4 [c] {s} x (ADDQ y y)) // result: (LEAQ8 [c] {s} x y) for { c := auxIntToInt32(v.AuxInt) s := auxToSym(v.Aux) x := v_0 - z := v_1 - if z.Op != OpAMD64ADDQ { + if v_1.Op != OpAMD64ADDQ { break } - y := z.Args[1] - if y != z.Args[0] || !(x != z) { + y := v_1.Args[1] + if y != v_1.Args[0] { break } v.reset(OpAMD64LEAQ8) @@ -13454,198 +13442,906 @@ func rewriteValueAMD64_OpAMD64MOVWstoreconst(v *Value) bool { if !(ValAndOff(sc).canAdd32(off)) { break } - v.reset(OpAMD64MOVWstoreconst) - v.AuxInt = valAndOffToAuxInt(ValAndOff(sc).addOffset32(off)) - v.Aux = symToAux(s) - v.AddArg2(ptr, mem) + v.reset(OpAMD64MOVWstoreconst) + v.AuxInt = valAndOffToAuxInt(ValAndOff(sc).addOffset32(off)) + v.Aux = symToAux(s) + v.AddArg2(ptr, mem) + return true + } + // match: (MOVWstoreconst [sc] {sym1} (LEAQ [off] {sym2} ptr) mem) + // cond: canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd32(off) + // result: (MOVWstoreconst [ValAndOff(sc).addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem) + for { + sc := auxIntToValAndOff(v.AuxInt) + sym1 := auxToSym(v.Aux) + if v_0.Op != OpAMD64LEAQ { + break + } + off := auxIntToInt32(v_0.AuxInt) + sym2 := auxToSym(v_0.Aux) + ptr := v_0.Args[0] + mem := v_1 + if !(canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd32(off)) { + break + } + v.reset(OpAMD64MOVWstoreconst) + v.AuxInt = valAndOffToAuxInt(ValAndOff(sc).addOffset32(off)) + v.Aux = symToAux(mergeSym(sym1, sym2)) + v.AddArg2(ptr, mem) + return true + } + return false +} +func rewriteValueAMD64_OpAMD64MULL(v *Value) bool { + v_1 := v.Args[1] + v_0 := v.Args[0] + // match: (MULL x (MOVLconst [c])) + // result: (MULLconst [c] x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x := v_0 + if v_1.Op != OpAMD64MOVLconst { + continue + } + c := auxIntToInt32(v_1.AuxInt) + v.reset(OpAMD64MULLconst) + v.AuxInt = int32ToAuxInt(c) + v.AddArg(x) + return true + } + break + } + return false +} +func rewriteValueAMD64_OpAMD64MULLconst(v *Value) bool { + v_0 := v.Args[0] + b := v.Block + // match: (MULLconst [c] (MULLconst [d] x)) + // result: (MULLconst [c * d] x) + for { + c := auxIntToInt32(v.AuxInt) + if v_0.Op != OpAMD64MULLconst { + break + } + d := auxIntToInt32(v_0.AuxInt) + x := v_0.Args[0] + v.reset(OpAMD64MULLconst) + v.AuxInt = int32ToAuxInt(c * d) + v.AddArg(x) + return true + } + // match: (MULLconst [-9] x) + // result: (NEGL (LEAL8 x x)) + for { + if auxIntToInt32(v.AuxInt) != -9 { + break + } + x := v_0 + v.reset(OpAMD64NEGL) + v0 := b.NewValue0(v.Pos, OpAMD64LEAL8, v.Type) + v0.AddArg2(x, x) + v.AddArg(v0) + return true + } + // match: (MULLconst [-5] x) + // result: (NEGL (LEAL4 x x)) + for { + if auxIntToInt32(v.AuxInt) != -5 { + break + } + x := v_0 + v.reset(OpAMD64NEGL) + v0 := b.NewValue0(v.Pos, OpAMD64LEAL4, v.Type) + v0.AddArg2(x, x) + v.AddArg(v0) + return true + } + // match: (MULLconst [-3] x) + // result: (NEGL (LEAL2 x x)) + for { + if auxIntToInt32(v.AuxInt) != -3 { + break + } + x := v_0 + v.reset(OpAMD64NEGL) + v0 := b.NewValue0(v.Pos, OpAMD64LEAL2, v.Type) + v0.AddArg2(x, x) + v.AddArg(v0) + return true + } + // match: (MULLconst [-1] x) + // result: (NEGL x) + for { + if auxIntToInt32(v.AuxInt) != -1 { + break + } + x := v_0 + v.reset(OpAMD64NEGL) + v.AddArg(x) + return true + } + // match: (MULLconst [ 0] _) + // result: (MOVLconst [0]) + for { + if auxIntToInt32(v.AuxInt) != 0 { + break + } + v.reset(OpAMD64MOVLconst) + v.AuxInt = int32ToAuxInt(0) + return true + } + // match: (MULLconst [ 1] x) + // result: x + for { + if auxIntToInt32(v.AuxInt) != 1 { + break + } + x := v_0 + v.copyOf(x) + return true + } + // match: (MULLconst [ 3] x) + // result: (LEAL2 x x) + for { + if auxIntToInt32(v.AuxInt) != 3 { + break + } + x := v_0 + v.reset(OpAMD64LEAL2) + v.AddArg2(x, x) + return true + } + // match: (MULLconst [ 5] x) + // result: (LEAL4 x x) + for { + if auxIntToInt32(v.AuxInt) != 5 { + break + } + x := v_0 + v.reset(OpAMD64LEAL4) + v.AddArg2(x, x) + return true + } + // match: (MULLconst [ 7] x) + // result: (LEAL2 x (LEAL2 x x)) + for { + if auxIntToInt32(v.AuxInt) != 7 { + break + } + x := v_0 + v.reset(OpAMD64LEAL2) + v0 := b.NewValue0(v.Pos, OpAMD64LEAL2, v.Type) + v0.AddArg2(x, x) + v.AddArg2(x, v0) + return true + } + // match: (MULLconst [ 9] x) + // result: (LEAL8 x x) + for { + if auxIntToInt32(v.AuxInt) != 9 { + break + } + x := v_0 + v.reset(OpAMD64LEAL8) + v.AddArg2(x, x) + return true + } + // match: (MULLconst [11] x) + // result: (LEAL2 x (LEAL4 x x)) + for { + if auxIntToInt32(v.AuxInt) != 11 { + break + } + x := v_0 + v.reset(OpAMD64LEAL2) + v0 := b.NewValue0(v.Pos, OpAMD64LEAL4, v.Type) + v0.AddArg2(x, x) + v.AddArg2(x, v0) + return true + } + // match: (MULLconst [13] x) + // result: (LEAL4 x (LEAL2 x x)) + for { + if auxIntToInt32(v.AuxInt) != 13 { + break + } + x := v_0 + v.reset(OpAMD64LEAL4) + v0 := b.NewValue0(v.Pos, OpAMD64LEAL2, v.Type) + v0.AddArg2(x, x) + v.AddArg2(x, v0) + return true + } + // match: (MULLconst [19] x) + // result: (LEAL2 x (LEAL8 x x)) + for { + if auxIntToInt32(v.AuxInt) != 19 { + break + } + x := v_0 + v.reset(OpAMD64LEAL2) + v0 := b.NewValue0(v.Pos, OpAMD64LEAL8, v.Type) + v0.AddArg2(x, x) + v.AddArg2(x, v0) + return true + } + // match: (MULLconst [21] x) + // result: (LEAL4 x (LEAL4 x x)) + for { + if auxIntToInt32(v.AuxInt) != 21 { + break + } + x := v_0 + v.reset(OpAMD64LEAL4) + v0 := b.NewValue0(v.Pos, OpAMD64LEAL4, v.Type) + v0.AddArg2(x, x) + v.AddArg2(x, v0) + return true + } + // match: (MULLconst [25] x) + // result: (LEAL8 x (LEAL2 x x)) + for { + if auxIntToInt32(v.AuxInt) != 25 { + break + } + x := v_0 + v.reset(OpAMD64LEAL8) + v0 := b.NewValue0(v.Pos, OpAMD64LEAL2, v.Type) + v0.AddArg2(x, x) + v.AddArg2(x, v0) + return true + } + // match: (MULLconst [27] x) + // result: (LEAL8 (LEAL2 x x) (LEAL2 x x)) + for { + if auxIntToInt32(v.AuxInt) != 27 { + break + } + x := v_0 + v.reset(OpAMD64LEAL8) + v0 := b.NewValue0(v.Pos, OpAMD64LEAL2, v.Type) + v0.AddArg2(x, x) + v.AddArg2(v0, v0) + return true + } + // match: (MULLconst [37] x) + // result: (LEAL4 x (LEAL8 x x)) + for { + if auxIntToInt32(v.AuxInt) != 37 { + break + } + x := v_0 + v.reset(OpAMD64LEAL4) + v0 := b.NewValue0(v.Pos, OpAMD64LEAL8, v.Type) + v0.AddArg2(x, x) + v.AddArg2(x, v0) + return true + } + // match: (MULLconst [41] x) + // result: (LEAL8 x (LEAL4 x x)) + for { + if auxIntToInt32(v.AuxInt) != 41 { + break + } + x := v_0 + v.reset(OpAMD64LEAL8) + v0 := b.NewValue0(v.Pos, OpAMD64LEAL4, v.Type) + v0.AddArg2(x, x) + v.AddArg2(x, v0) + return true + } + // match: (MULLconst [45] x) + // result: (LEAL8 (LEAL4 x x) (LEAL4 x x)) + for { + if auxIntToInt32(v.AuxInt) != 45 { + break + } + x := v_0 + v.reset(OpAMD64LEAL8) + v0 := b.NewValue0(v.Pos, OpAMD64LEAL4, v.Type) + v0.AddArg2(x, x) + v.AddArg2(v0, v0) + return true + } + // match: (MULLconst [73] x) + // result: (LEAL8 x (LEAL8 x x)) + for { + if auxIntToInt32(v.AuxInt) != 73 { + break + } + x := v_0 + v.reset(OpAMD64LEAL8) + v0 := b.NewValue0(v.Pos, OpAMD64LEAL8, v.Type) + v0.AddArg2(x, x) + v.AddArg2(x, v0) + return true + } + // match: (MULLconst [81] x) + // result: (LEAL8 (LEAL8 x x) (LEAL8 x x)) + for { + if auxIntToInt32(v.AuxInt) != 81 { + break + } + x := v_0 + v.reset(OpAMD64LEAL8) + v0 := b.NewValue0(v.Pos, OpAMD64LEAL8, v.Type) + v0.AddArg2(x, x) + v.AddArg2(v0, v0) + return true + } + // match: (MULLconst [c] x) + // cond: isPowerOfTwo(int64(c)+1) && c >= 15 + // result: (SUBL (SHLLconst [int8(log64(int64(c)+1))] x) x) + for { + c := auxIntToInt32(v.AuxInt) + x := v_0 + if !(isPowerOfTwo(int64(c)+1) && c >= 15) { + break + } + v.reset(OpAMD64SUBL) + v0 := b.NewValue0(v.Pos, OpAMD64SHLLconst, v.Type) + v0.AuxInt = int8ToAuxInt(int8(log64(int64(c) + 1))) + v0.AddArg(x) + v.AddArg2(v0, x) + return true + } + // match: (MULLconst [c] x) + // cond: isPowerOfTwo(c-1) && c >= 17 + // result: (LEAL1 (SHLLconst [int8(log32(c-1))] x) x) + for { + c := auxIntToInt32(v.AuxInt) + x := v_0 + if !(isPowerOfTwo(c-1) && c >= 17) { + break + } + v.reset(OpAMD64LEAL1) + v0 := b.NewValue0(v.Pos, OpAMD64SHLLconst, v.Type) + v0.AuxInt = int8ToAuxInt(int8(log32(c - 1))) + v0.AddArg(x) + v.AddArg2(v0, x) + return true + } + // match: (MULLconst [c] x) + // cond: isPowerOfTwo(c-2) && c >= 34 + // result: (LEAL2 (SHLLconst [int8(log32(c-2))] x) x) + for { + c := auxIntToInt32(v.AuxInt) + x := v_0 + if !(isPowerOfTwo(c-2) && c >= 34) { + break + } + v.reset(OpAMD64LEAL2) + v0 := b.NewValue0(v.Pos, OpAMD64SHLLconst, v.Type) + v0.AuxInt = int8ToAuxInt(int8(log32(c - 2))) + v0.AddArg(x) + v.AddArg2(v0, x) + return true + } + // match: (MULLconst [c] x) + // cond: isPowerOfTwo(c-4) && c >= 68 + // result: (LEAL4 (SHLLconst [int8(log32(c-4))] x) x) + for { + c := auxIntToInt32(v.AuxInt) + x := v_0 + if !(isPowerOfTwo(c-4) && c >= 68) { + break + } + v.reset(OpAMD64LEAL4) + v0 := b.NewValue0(v.Pos, OpAMD64SHLLconst, v.Type) + v0.AuxInt = int8ToAuxInt(int8(log32(c - 4))) + v0.AddArg(x) + v.AddArg2(v0, x) + return true + } + // match: (MULLconst [c] x) + // cond: isPowerOfTwo(c-8) && c >= 136 + // result: (LEAL8 (SHLLconst [int8(log32(c-8))] x) x) + for { + c := auxIntToInt32(v.AuxInt) + x := v_0 + if !(isPowerOfTwo(c-8) && c >= 136) { + break + } + v.reset(OpAMD64LEAL8) + v0 := b.NewValue0(v.Pos, OpAMD64SHLLconst, v.Type) + v0.AuxInt = int8ToAuxInt(int8(log32(c - 8))) + v0.AddArg(x) + v.AddArg2(v0, x) + return true + } + // match: (MULLconst [c] x) + // cond: c%3 == 0 && isPowerOfTwo(c/3) + // result: (SHLLconst [int8(log32(c/3))] (LEAL2 x x)) + for { + c := auxIntToInt32(v.AuxInt) + x := v_0 + if !(c%3 == 0 && isPowerOfTwo(c/3)) { + break + } + v.reset(OpAMD64SHLLconst) + v.AuxInt = int8ToAuxInt(int8(log32(c / 3))) + v0 := b.NewValue0(v.Pos, OpAMD64LEAL2, v.Type) + v0.AddArg2(x, x) + v.AddArg(v0) + return true + } + // match: (MULLconst [c] x) + // cond: c%5 == 0 && isPowerOfTwo(c/5) + // result: (SHLLconst [int8(log32(c/5))] (LEAL4 x x)) + for { + c := auxIntToInt32(v.AuxInt) + x := v_0 + if !(c%5 == 0 && isPowerOfTwo(c/5)) { + break + } + v.reset(OpAMD64SHLLconst) + v.AuxInt = int8ToAuxInt(int8(log32(c / 5))) + v0 := b.NewValue0(v.Pos, OpAMD64LEAL4, v.Type) + v0.AddArg2(x, x) + v.AddArg(v0) + return true + } + // match: (MULLconst [c] x) + // cond: c%9 == 0 && isPowerOfTwo(c/9) + // result: (SHLLconst [int8(log32(c/9))] (LEAL8 x x)) + for { + c := auxIntToInt32(v.AuxInt) + x := v_0 + if !(c%9 == 0 && isPowerOfTwo(c/9)) { + break + } + v.reset(OpAMD64SHLLconst) + v.AuxInt = int8ToAuxInt(int8(log32(c / 9))) + v0 := b.NewValue0(v.Pos, OpAMD64LEAL8, v.Type) + v0.AddArg2(x, x) + v.AddArg(v0) + return true + } + // match: (MULLconst [c] (MOVLconst [d])) + // result: (MOVLconst [c*d]) + for { + c := auxIntToInt32(v.AuxInt) + if v_0.Op != OpAMD64MOVLconst { + break + } + d := auxIntToInt32(v_0.AuxInt) + v.reset(OpAMD64MOVLconst) + v.AuxInt = int32ToAuxInt(c * d) + return true + } + return false +} +func rewriteValueAMD64_OpAMD64MULQ(v *Value) bool { + v_1 := v.Args[1] + v_0 := v.Args[0] + // match: (MULQ x (MOVQconst [c])) + // cond: is32Bit(c) + // result: (MULQconst [int32(c)] x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x := v_0 + if v_1.Op != OpAMD64MOVQconst { + continue + } + c := auxIntToInt64(v_1.AuxInt) + if !(is32Bit(c)) { + continue + } + v.reset(OpAMD64MULQconst) + v.AuxInt = int32ToAuxInt(int32(c)) + v.AddArg(x) + return true + } + break + } + return false +} +func rewriteValueAMD64_OpAMD64MULQconst(v *Value) bool { + v_0 := v.Args[0] + b := v.Block + // match: (MULQconst [c] (MULQconst [d] x)) + // cond: is32Bit(int64(c)*int64(d)) + // result: (MULQconst [c * d] x) + for { + c := auxIntToInt32(v.AuxInt) + if v_0.Op != OpAMD64MULQconst { + break + } + d := auxIntToInt32(v_0.AuxInt) + x := v_0.Args[0] + if !(is32Bit(int64(c) * int64(d))) { + break + } + v.reset(OpAMD64MULQconst) + v.AuxInt = int32ToAuxInt(c * d) + v.AddArg(x) + return true + } + // match: (MULQconst [-9] x) + // result: (NEGQ (LEAQ8 x x)) + for { + if auxIntToInt32(v.AuxInt) != -9 { + break + } + x := v_0 + v.reset(OpAMD64NEGQ) + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ8, v.Type) + v0.AddArg2(x, x) + v.AddArg(v0) + return true + } + // match: (MULQconst [-5] x) + // result: (NEGQ (LEAQ4 x x)) + for { + if auxIntToInt32(v.AuxInt) != -5 { + break + } + x := v_0 + v.reset(OpAMD64NEGQ) + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ4, v.Type) + v0.AddArg2(x, x) + v.AddArg(v0) + return true + } + // match: (MULQconst [-3] x) + // result: (NEGQ (LEAQ2 x x)) + for { + if auxIntToInt32(v.AuxInt) != -3 { + break + } + x := v_0 + v.reset(OpAMD64NEGQ) + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ2, v.Type) + v0.AddArg2(x, x) + v.AddArg(v0) + return true + } + // match: (MULQconst [-1] x) + // result: (NEGQ x) + for { + if auxIntToInt32(v.AuxInt) != -1 { + break + } + x := v_0 + v.reset(OpAMD64NEGQ) + v.AddArg(x) + return true + } + // match: (MULQconst [ 0] _) + // result: (MOVQconst [0]) + for { + if auxIntToInt32(v.AuxInt) != 0 { + break + } + v.reset(OpAMD64MOVQconst) + v.AuxInt = int64ToAuxInt(0) + return true + } + // match: (MULQconst [ 1] x) + // result: x + for { + if auxIntToInt32(v.AuxInt) != 1 { + break + } + x := v_0 + v.copyOf(x) + return true + } + // match: (MULQconst [ 3] x) + // result: (LEAQ2 x x) + for { + if auxIntToInt32(v.AuxInt) != 3 { + break + } + x := v_0 + v.reset(OpAMD64LEAQ2) + v.AddArg2(x, x) + return true + } + // match: (MULQconst [ 5] x) + // result: (LEAQ4 x x) + for { + if auxIntToInt32(v.AuxInt) != 5 { + break + } + x := v_0 + v.reset(OpAMD64LEAQ4) + v.AddArg2(x, x) + return true + } + // match: (MULQconst [ 7] x) + // result: (LEAQ2 x (LEAQ2 x x)) + for { + if auxIntToInt32(v.AuxInt) != 7 { + break + } + x := v_0 + v.reset(OpAMD64LEAQ2) + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ2, v.Type) + v0.AddArg2(x, x) + v.AddArg2(x, v0) + return true + } + // match: (MULQconst [ 9] x) + // result: (LEAQ8 x x) + for { + if auxIntToInt32(v.AuxInt) != 9 { + break + } + x := v_0 + v.reset(OpAMD64LEAQ8) + v.AddArg2(x, x) + return true + } + // match: (MULQconst [11] x) + // result: (LEAQ2 x (LEAQ4 x x)) + for { + if auxIntToInt32(v.AuxInt) != 11 { + break + } + x := v_0 + v.reset(OpAMD64LEAQ2) + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ4, v.Type) + v0.AddArg2(x, x) + v.AddArg2(x, v0) + return true + } + // match: (MULQconst [13] x) + // result: (LEAQ4 x (LEAQ2 x x)) + for { + if auxIntToInt32(v.AuxInt) != 13 { + break + } + x := v_0 + v.reset(OpAMD64LEAQ4) + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ2, v.Type) + v0.AddArg2(x, x) + v.AddArg2(x, v0) + return true + } + // match: (MULQconst [19] x) + // result: (LEAQ2 x (LEAQ8 x x)) + for { + if auxIntToInt32(v.AuxInt) != 19 { + break + } + x := v_0 + v.reset(OpAMD64LEAQ2) + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ8, v.Type) + v0.AddArg2(x, x) + v.AddArg2(x, v0) + return true + } + // match: (MULQconst [21] x) + // result: (LEAQ4 x (LEAQ4 x x)) + for { + if auxIntToInt32(v.AuxInt) != 21 { + break + } + x := v_0 + v.reset(OpAMD64LEAQ4) + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ4, v.Type) + v0.AddArg2(x, x) + v.AddArg2(x, v0) return true } - // match: (MOVWstoreconst [sc] {sym1} (LEAQ [off] {sym2} ptr) mem) - // cond: canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd32(off) - // result: (MOVWstoreconst [ValAndOff(sc).addOffset32(off)] {mergeSym(sym1, sym2)} ptr mem) + // match: (MULQconst [25] x) + // result: (LEAQ8 x (LEAQ2 x x)) for { - sc := auxIntToValAndOff(v.AuxInt) - sym1 := auxToSym(v.Aux) - if v_0.Op != OpAMD64LEAQ { + if auxIntToInt32(v.AuxInt) != 25 { break } - off := auxIntToInt32(v_0.AuxInt) - sym2 := auxToSym(v_0.Aux) - ptr := v_0.Args[0] - mem := v_1 - if !(canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd32(off)) { + x := v_0 + v.reset(OpAMD64LEAQ8) + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ2, v.Type) + v0.AddArg2(x, x) + v.AddArg2(x, v0) + return true + } + // match: (MULQconst [27] x) + // result: (LEAQ8 (LEAQ2 x x) (LEAQ2 x x)) + for { + if auxIntToInt32(v.AuxInt) != 27 { break } - v.reset(OpAMD64MOVWstoreconst) - v.AuxInt = valAndOffToAuxInt(ValAndOff(sc).addOffset32(off)) - v.Aux = symToAux(mergeSym(sym1, sym2)) - v.AddArg2(ptr, mem) + x := v_0 + v.reset(OpAMD64LEAQ8) + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ2, v.Type) + v0.AddArg2(x, x) + v.AddArg2(v0, v0) return true } - return false -} -func rewriteValueAMD64_OpAMD64MULL(v *Value) bool { - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MULL x (MOVLconst [c])) - // result: (MULLconst [c] x) + // match: (MULQconst [37] x) + // result: (LEAQ4 x (LEAQ8 x x)) for { - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - x := v_0 - if v_1.Op != OpAMD64MOVLconst { - continue - } - c := auxIntToInt32(v_1.AuxInt) - v.reset(OpAMD64MULLconst) - v.AuxInt = int32ToAuxInt(c) - v.AddArg(x) - return true + if auxIntToInt32(v.AuxInt) != 37 { + break } - break + x := v_0 + v.reset(OpAMD64LEAQ4) + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ8, v.Type) + v0.AddArg2(x, x) + v.AddArg2(x, v0) + return true } - return false -} -func rewriteValueAMD64_OpAMD64MULLconst(v *Value) bool { - v_0 := v.Args[0] - b := v.Block - config := b.Func.Config - // match: (MULLconst [c] (MULLconst [d] x)) - // result: (MULLconst [c * d] x) + // match: (MULQconst [41] x) + // result: (LEAQ8 x (LEAQ4 x x)) for { - c := auxIntToInt32(v.AuxInt) - if v_0.Op != OpAMD64MULLconst { + if auxIntToInt32(v.AuxInt) != 41 { break } - d := auxIntToInt32(v_0.AuxInt) - x := v_0.Args[0] - v.reset(OpAMD64MULLconst) - v.AuxInt = int32ToAuxInt(c * d) - v.AddArg(x) + x := v_0 + v.reset(OpAMD64LEAQ8) + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ4, v.Type) + v0.AddArg2(x, x) + v.AddArg2(x, v0) return true } - // match: (MULLconst [ 0] _) - // result: (MOVLconst [0]) + // match: (MULQconst [45] x) + // result: (LEAQ8 (LEAQ4 x x) (LEAQ4 x x)) for { - if auxIntToInt32(v.AuxInt) != 0 { + if auxIntToInt32(v.AuxInt) != 45 { break } - v.reset(OpAMD64MOVLconst) - v.AuxInt = int32ToAuxInt(0) + x := v_0 + v.reset(OpAMD64LEAQ8) + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ4, v.Type) + v0.AddArg2(x, x) + v.AddArg2(v0, v0) return true } - // match: (MULLconst [ 1] x) - // result: x + // match: (MULQconst [73] x) + // result: (LEAQ8 x (LEAQ8 x x)) for { - if auxIntToInt32(v.AuxInt) != 1 { + if auxIntToInt32(v.AuxInt) != 73 { break } x := v_0 - v.copyOf(x) + v.reset(OpAMD64LEAQ8) + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ8, v.Type) + v0.AddArg2(x, x) + v.AddArg2(x, v0) return true } - // match: (MULLconst [c] x) - // cond: v.Type.Size() <= 4 && canMulStrengthReduce32(config, c) - // result: {mulStrengthReduce32(v, x, c)} + // match: (MULQconst [81] x) + // result: (LEAQ8 (LEAQ8 x x) (LEAQ8 x x)) + for { + if auxIntToInt32(v.AuxInt) != 81 { + break + } + x := v_0 + v.reset(OpAMD64LEAQ8) + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ8, v.Type) + v0.AddArg2(x, x) + v.AddArg2(v0, v0) + return true + } + // match: (MULQconst [c] x) + // cond: isPowerOfTwo(int64(c)+1) && c >= 15 + // result: (SUBQ (SHLQconst [int8(log64(int64(c)+1))] x) x) for { c := auxIntToInt32(v.AuxInt) x := v_0 - if !(v.Type.Size() <= 4 && canMulStrengthReduce32(config, c)) { + if !(isPowerOfTwo(int64(c)+1) && c >= 15) { break } - v.copyOf(mulStrengthReduce32(v, x, c)) + v.reset(OpAMD64SUBQ) + v0 := b.NewValue0(v.Pos, OpAMD64SHLQconst, v.Type) + v0.AuxInt = int8ToAuxInt(int8(log64(int64(c) + 1))) + v0.AddArg(x) + v.AddArg2(v0, x) return true } - // match: (MULLconst [c] (MOVLconst [d])) - // result: (MOVLconst [c*d]) + // match: (MULQconst [c] x) + // cond: isPowerOfTwo(c-1) && c >= 17 + // result: (LEAQ1 (SHLQconst [int8(log32(c-1))] x) x) for { c := auxIntToInt32(v.AuxInt) - if v_0.Op != OpAMD64MOVLconst { + x := v_0 + if !(isPowerOfTwo(c-1) && c >= 17) { break } - d := auxIntToInt32(v_0.AuxInt) - v.reset(OpAMD64MOVLconst) - v.AuxInt = int32ToAuxInt(c * d) + v.reset(OpAMD64LEAQ1) + v0 := b.NewValue0(v.Pos, OpAMD64SHLQconst, v.Type) + v0.AuxInt = int8ToAuxInt(int8(log32(c - 1))) + v0.AddArg(x) + v.AddArg2(v0, x) return true } - return false -} -func rewriteValueAMD64_OpAMD64MULQ(v *Value) bool { - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (MULQ x (MOVQconst [c])) - // cond: is32Bit(c) - // result: (MULQconst [int32(c)] x) + // match: (MULQconst [c] x) + // cond: isPowerOfTwo(c-2) && c >= 34 + // result: (LEAQ2 (SHLQconst [int8(log32(c-2))] x) x) for { - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - x := v_0 - if v_1.Op != OpAMD64MOVQconst { - continue - } - c := auxIntToInt64(v_1.AuxInt) - if !(is32Bit(c)) { - continue - } - v.reset(OpAMD64MULQconst) - v.AuxInt = int32ToAuxInt(int32(c)) - v.AddArg(x) - return true + c := auxIntToInt32(v.AuxInt) + x := v_0 + if !(isPowerOfTwo(c-2) && c >= 34) { + break } - break + v.reset(OpAMD64LEAQ2) + v0 := b.NewValue0(v.Pos, OpAMD64SHLQconst, v.Type) + v0.AuxInt = int8ToAuxInt(int8(log32(c - 2))) + v0.AddArg(x) + v.AddArg2(v0, x) + return true } - return false -} -func rewriteValueAMD64_OpAMD64MULQconst(v *Value) bool { - v_0 := v.Args[0] - b := v.Block - config := b.Func.Config - // match: (MULQconst [c] (MULQconst [d] x)) - // cond: is32Bit(int64(c)*int64(d)) - // result: (MULQconst [c * d] x) + // match: (MULQconst [c] x) + // cond: isPowerOfTwo(c-4) && c >= 68 + // result: (LEAQ4 (SHLQconst [int8(log32(c-4))] x) x) for { c := auxIntToInt32(v.AuxInt) - if v_0.Op != OpAMD64MULQconst { + x := v_0 + if !(isPowerOfTwo(c-4) && c >= 68) { break } - d := auxIntToInt32(v_0.AuxInt) - x := v_0.Args[0] - if !(is32Bit(int64(c) * int64(d))) { + v.reset(OpAMD64LEAQ4) + v0 := b.NewValue0(v.Pos, OpAMD64SHLQconst, v.Type) + v0.AuxInt = int8ToAuxInt(int8(log32(c - 4))) + v0.AddArg(x) + v.AddArg2(v0, x) + return true + } + // match: (MULQconst [c] x) + // cond: isPowerOfTwo(c-8) && c >= 136 + // result: (LEAQ8 (SHLQconst [int8(log32(c-8))] x) x) + for { + c := auxIntToInt32(v.AuxInt) + x := v_0 + if !(isPowerOfTwo(c-8) && c >= 136) { break } - v.reset(OpAMD64MULQconst) - v.AuxInt = int32ToAuxInt(c * d) - v.AddArg(x) + v.reset(OpAMD64LEAQ8) + v0 := b.NewValue0(v.Pos, OpAMD64SHLQconst, v.Type) + v0.AuxInt = int8ToAuxInt(int8(log32(c - 8))) + v0.AddArg(x) + v.AddArg2(v0, x) return true } - // match: (MULQconst [ 0] _) - // result: (MOVQconst [0]) + // match: (MULQconst [c] x) + // cond: c%3 == 0 && isPowerOfTwo(c/3) + // result: (SHLQconst [int8(log32(c/3))] (LEAQ2 x x)) for { - if auxIntToInt32(v.AuxInt) != 0 { + c := auxIntToInt32(v.AuxInt) + x := v_0 + if !(c%3 == 0 && isPowerOfTwo(c/3)) { break } - v.reset(OpAMD64MOVQconst) - v.AuxInt = int64ToAuxInt(0) + v.reset(OpAMD64SHLQconst) + v.AuxInt = int8ToAuxInt(int8(log32(c / 3))) + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ2, v.Type) + v0.AddArg2(x, x) + v.AddArg(v0) return true } - // match: (MULQconst [ 1] x) - // result: x + // match: (MULQconst [c] x) + // cond: c%5 == 0 && isPowerOfTwo(c/5) + // result: (SHLQconst [int8(log32(c/5))] (LEAQ4 x x)) for { - if auxIntToInt32(v.AuxInt) != 1 { + c := auxIntToInt32(v.AuxInt) + x := v_0 + if !(c%5 == 0 && isPowerOfTwo(c/5)) { break } - x := v_0 - v.copyOf(x) + v.reset(OpAMD64SHLQconst) + v.AuxInt = int8ToAuxInt(int8(log32(c / 5))) + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ4, v.Type) + v0.AddArg2(x, x) + v.AddArg(v0) return true } // match: (MULQconst [c] x) - // cond: canMulStrengthReduce(config, int64(c)) - // result: {mulStrengthReduce(v, x, int64(c))} + // cond: c%9 == 0 && isPowerOfTwo(c/9) + // result: (SHLQconst [int8(log32(c/9))] (LEAQ8 x x)) for { c := auxIntToInt32(v.AuxInt) x := v_0 - if !(canMulStrengthReduce(config, int64(c))) { + if !(c%9 == 0 && isPowerOfTwo(c/9)) { break } - v.copyOf(mulStrengthReduce(v, x, int64(c))) + v.reset(OpAMD64SHLQconst) + v.AuxInt = int8ToAuxInt(int8(log32(c / 9))) + v0 := b.NewValue0(v.Pos, OpAMD64LEAQ8, v.Type) + v0.AddArg2(x, x) + v.AddArg(v0) return true } // match: (MULQconst [c] (MOVQconst [d])) @@ -29295,42 +29991,6 @@ func rewriteValueAMD64_OpSelect0(v *Value) bool { v.AddArg2(val, v0) return true } - // match: (Select0 a:(ADDQconstflags [c] x)) - // cond: a.Uses == 1 - // result: (ADDQconst [c] x) - for { - a := v_0 - if a.Op != OpAMD64ADDQconstflags { - break - } - c := auxIntToInt32(a.AuxInt) - x := a.Args[0] - if !(a.Uses == 1) { - break - } - v.reset(OpAMD64ADDQconst) - v.AuxInt = int32ToAuxInt(c) - v.AddArg(x) - return true - } - // match: (Select0 a:(ADDLconstflags [c] x)) - // cond: a.Uses == 1 - // result: (ADDLconst [c] x) - for { - a := v_0 - if a.Op != OpAMD64ADDLconstflags { - break - } - c := auxIntToInt32(a.AuxInt) - x := a.Args[0] - if !(a.Uses == 1) { - break - } - v.reset(OpAMD64ADDLconst) - v.AuxInt = int32ToAuxInt(c) - v.AddArg(x) - return true - } return false } func rewriteValueAMD64_OpSelect1(v *Value) bool { @@ -30486,52 +31146,6 @@ func rewriteBlockAMD64(b *Block) bool { } break } - // match: (EQ t:(TESTQ a:(ADDQconst [c] x) a)) - // cond: t.Uses == 1 && flagify(a) - // result: (EQ (Select1 a.Args[0])) - for b.Controls[0].Op == OpAMD64TESTQ { - t := b.Controls[0] - _ = t.Args[1] - t_0 := t.Args[0] - t_1 := t.Args[1] - for _i0 := 0; _i0 <= 1; _i0, t_0, t_1 = _i0+1, t_1, t_0 { - a := t_0 - if a.Op != OpAMD64ADDQconst { - continue - } - if a != t_1 || !(t.Uses == 1 && flagify(a)) { - continue - } - v0 := b.NewValue0(t.Pos, OpSelect1, types.TypeFlags) - v0.AddArg(a.Args[0]) - b.resetWithControl(BlockAMD64EQ, v0) - return true - } - break - } - // match: (EQ t:(TESTL a:(ADDLconst [c] x) a)) - // cond: t.Uses == 1 && flagify(a) - // result: (EQ (Select1 a.Args[0])) - for b.Controls[0].Op == OpAMD64TESTL { - t := b.Controls[0] - _ = t.Args[1] - t_0 := t.Args[0] - t_1 := t.Args[1] - for _i0 := 0; _i0 <= 1; _i0, t_0, t_1 = _i0+1, t_1, t_0 { - a := t_0 - if a.Op != OpAMD64ADDLconst { - continue - } - if a != t_1 || !(t.Uses == 1 && flagify(a)) { - continue - } - v0 := b.NewValue0(t.Pos, OpSelect1, types.TypeFlags) - v0.AddArg(a.Args[0]) - b.resetWithControl(BlockAMD64EQ, v0) - return true - } - break - } case BlockAMD64GE: // match: (GE c:(CMPQconst [128] z) yes no) // cond: c.Uses == 1 @@ -31531,52 +32145,6 @@ func rewriteBlockAMD64(b *Block) bool { } break } - // match: (NE t:(TESTQ a:(ADDQconst [c] x) a)) - // cond: t.Uses == 1 && flagify(a) - // result: (NE (Select1 a.Args[0])) - for b.Controls[0].Op == OpAMD64TESTQ { - t := b.Controls[0] - _ = t.Args[1] - t_0 := t.Args[0] - t_1 := t.Args[1] - for _i0 := 0; _i0 <= 1; _i0, t_0, t_1 = _i0+1, t_1, t_0 { - a := t_0 - if a.Op != OpAMD64ADDQconst { - continue - } - if a != t_1 || !(t.Uses == 1 && flagify(a)) { - continue - } - v0 := b.NewValue0(t.Pos, OpSelect1, types.TypeFlags) - v0.AddArg(a.Args[0]) - b.resetWithControl(BlockAMD64NE, v0) - return true - } - break - } - // match: (NE t:(TESTL a:(ADDLconst [c] x) a)) - // cond: t.Uses == 1 && flagify(a) - // result: (NE (Select1 a.Args[0])) - for b.Controls[0].Op == OpAMD64TESTL { - t := b.Controls[0] - _ = t.Args[1] - t_0 := t.Args[0] - t_1 := t.Args[1] - for _i0 := 0; _i0 <= 1; _i0, t_0, t_1 = _i0+1, t_1, t_0 { - a := t_0 - if a.Op != OpAMD64ADDLconst { - continue - } - if a != t_1 || !(t.Uses == 1 && flagify(a)) { - continue - } - v0 := b.NewValue0(t.Pos, OpSelect1, types.TypeFlags) - v0.AddArg(a.Args[0]) - b.resetWithControl(BlockAMD64NE, v0) - return true - } - break - } case BlockAMD64UGE: // match: (UGE (TESTQ x x) yes no) // result: (First yes no) diff --git a/src/cmd/compile/internal/ssa/rewriteARM64.go b/src/cmd/compile/internal/ssa/rewriteARM64.go index 792967c001ba84..7f2feabbf77b13 100644 --- a/src/cmd/compile/internal/ssa/rewriteARM64.go +++ b/src/cmd/compile/internal/ssa/rewriteARM64.go @@ -12331,7 +12331,6 @@ func rewriteValueARM64_OpARM64MUL(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block - config := b.Func.Config // match: (MUL (NEG x) y) // result: (MNEG x y) for { @@ -12347,6 +12346,20 @@ func rewriteValueARM64_OpARM64MUL(v *Value) bool { } break } + // match: (MUL x (MOVDconst [-1])) + // result: (NEG x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x := v_0 + if v_1.Op != OpARM64MOVDconst || auxIntToInt64(v_1.AuxInt) != -1 { + continue + } + v.reset(OpARM64NEG) + v.AddArg(x) + return true + } + break + } // match: (MUL _ (MOVDconst [0])) // result: (MOVDconst [0]) for { @@ -12374,8 +12387,116 @@ func rewriteValueARM64_OpARM64MUL(v *Value) bool { break } // match: (MUL x (MOVDconst [c])) - // cond: canMulStrengthReduce(config, c) - // result: {mulStrengthReduce(v, x, c)} + // cond: isPowerOfTwo(c) + // result: (SLLconst [log64(c)] x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x := v_0 + if v_1.Op != OpARM64MOVDconst { + continue + } + c := auxIntToInt64(v_1.AuxInt) + if !(isPowerOfTwo(c)) { + continue + } + v.reset(OpARM64SLLconst) + v.AuxInt = int64ToAuxInt(log64(c)) + v.AddArg(x) + return true + } + break + } + // match: (MUL x (MOVDconst [c])) + // cond: isPowerOfTwo(c-1) && c >= 3 + // result: (ADDshiftLL x x [log64(c-1)]) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x := v_0 + if v_1.Op != OpARM64MOVDconst { + continue + } + c := auxIntToInt64(v_1.AuxInt) + if !(isPowerOfTwo(c-1) && c >= 3) { + continue + } + v.reset(OpARM64ADDshiftLL) + v.AuxInt = int64ToAuxInt(log64(c - 1)) + v.AddArg2(x, x) + return true + } + break + } + // match: (MUL x (MOVDconst [c])) + // cond: isPowerOfTwo(c+1) && c >= 7 + // result: (ADDshiftLL (NEG x) x [log64(c+1)]) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x := v_0 + if v_1.Op != OpARM64MOVDconst { + continue + } + c := auxIntToInt64(v_1.AuxInt) + if !(isPowerOfTwo(c+1) && c >= 7) { + continue + } + v.reset(OpARM64ADDshiftLL) + v.AuxInt = int64ToAuxInt(log64(c + 1)) + v0 := b.NewValue0(v.Pos, OpARM64NEG, x.Type) + v0.AddArg(x) + v.AddArg2(v0, x) + return true + } + break + } + // match: (MUL x (MOVDconst [c])) + // cond: c%3 == 0 && isPowerOfTwo(c/3) + // result: (SLLconst [log64(c/3)] (ADDshiftLL x x [1])) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x := v_0 + if v_1.Op != OpARM64MOVDconst { + continue + } + c := auxIntToInt64(v_1.AuxInt) + if !(c%3 == 0 && isPowerOfTwo(c/3)) { + continue + } + v.reset(OpARM64SLLconst) + v.AuxInt = int64ToAuxInt(log64(c / 3)) + v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) + v0.AuxInt = int64ToAuxInt(1) + v0.AddArg2(x, x) + v.AddArg(v0) + return true + } + break + } + // match: (MUL x (MOVDconst [c])) + // cond: c%5 == 0 && isPowerOfTwo(c/5) + // result: (SLLconst [log64(c/5)] (ADDshiftLL x x [2])) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x := v_0 + if v_1.Op != OpARM64MOVDconst { + continue + } + c := auxIntToInt64(v_1.AuxInt) + if !(c%5 == 0 && isPowerOfTwo(c/5)) { + continue + } + v.reset(OpARM64SLLconst) + v.AuxInt = int64ToAuxInt(log64(c / 5)) + v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) + v0.AuxInt = int64ToAuxInt(2) + v0.AddArg2(x, x) + v.AddArg(v0) + return true + } + break + } + // match: (MUL x (MOVDconst [c])) + // cond: c%7 == 0 && isPowerOfTwo(c/7) + // result: (SLLconst [log64(c/7)] (ADDshiftLL (NEG x) x [3])) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { x := v_0 @@ -12383,10 +12504,40 @@ func rewriteValueARM64_OpARM64MUL(v *Value) bool { continue } c := auxIntToInt64(v_1.AuxInt) - if !(canMulStrengthReduce(config, c)) { + if !(c%7 == 0 && isPowerOfTwo(c/7)) { continue } - v.copyOf(mulStrengthReduce(v, x, c)) + v.reset(OpARM64SLLconst) + v.AuxInt = int64ToAuxInt(log64(c / 7)) + v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) + v0.AuxInt = int64ToAuxInt(3) + v1 := b.NewValue0(v.Pos, OpARM64NEG, x.Type) + v1.AddArg(x) + v0.AddArg2(v1, x) + v.AddArg(v0) + return true + } + break + } + // match: (MUL x (MOVDconst [c])) + // cond: c%9 == 0 && isPowerOfTwo(c/9) + // result: (SLLconst [log64(c/9)] (ADDshiftLL x x [3])) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x := v_0 + if v_1.Op != OpARM64MOVDconst { + continue + } + c := auxIntToInt64(v_1.AuxInt) + if !(c%9 == 0 && isPowerOfTwo(c/9)) { + continue + } + v.reset(OpARM64SLLconst) + v.AuxInt = int64ToAuxInt(log64(c / 9)) + v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) + v0.AuxInt = int64ToAuxInt(3) + v0.AddArg2(x, x) + v.AddArg(v0) return true } break @@ -12415,7 +12566,6 @@ func rewriteValueARM64_OpARM64MULW(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block - config := b.Func.Config // match: (MULW (NEG x) y) // result: (MNEGW x y) for { @@ -12431,6 +12581,27 @@ func rewriteValueARM64_OpARM64MULW(v *Value) bool { } break } + // match: (MULW x (MOVDconst [c])) + // cond: int32(c)==-1 + // result: (MOVWUreg (NEG x)) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x := v_0 + if v_1.Op != OpARM64MOVDconst { + continue + } + c := auxIntToInt64(v_1.AuxInt) + if !(int32(c) == -1) { + continue + } + v.reset(OpARM64MOVWUreg) + v0 := b.NewValue0(v.Pos, OpARM64NEG, x.Type) + v0.AddArg(x) + v.AddArg(v0) + return true + } + break + } // match: (MULW _ (MOVDconst [c])) // cond: int32(c)==0 // result: (MOVDconst [0]) @@ -12469,8 +12640,30 @@ func rewriteValueARM64_OpARM64MULW(v *Value) bool { break } // match: (MULW x (MOVDconst [c])) - // cond: v.Type.Size() <= 4 && canMulStrengthReduce32(config, int32(c)) - // result: {mulStrengthReduce32(v, x, int32(c))} + // cond: isPowerOfTwo(c) + // result: (MOVWUreg (SLLconst [log64(c)] x)) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x := v_0 + if v_1.Op != OpARM64MOVDconst { + continue + } + c := auxIntToInt64(v_1.AuxInt) + if !(isPowerOfTwo(c)) { + continue + } + v.reset(OpARM64MOVWUreg) + v0 := b.NewValue0(v.Pos, OpARM64SLLconst, x.Type) + v0.AuxInt = int64ToAuxInt(log64(c)) + v0.AddArg(x) + v.AddArg(v0) + return true + } + break + } + // match: (MULW x (MOVDconst [c])) + // cond: isPowerOfTwo(c-1) && int32(c) >= 3 + // result: (MOVWUreg (ADDshiftLL x x [log64(c-1)])) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { x := v_0 @@ -12478,10 +12671,140 @@ func rewriteValueARM64_OpARM64MULW(v *Value) bool { continue } c := auxIntToInt64(v_1.AuxInt) - if !(v.Type.Size() <= 4 && canMulStrengthReduce32(config, int32(c))) { + if !(isPowerOfTwo(c-1) && int32(c) >= 3) { continue } - v.copyOf(mulStrengthReduce32(v, x, int32(c))) + v.reset(OpARM64MOVWUreg) + v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) + v0.AuxInt = int64ToAuxInt(log64(c - 1)) + v0.AddArg2(x, x) + v.AddArg(v0) + return true + } + break + } + // match: (MULW x (MOVDconst [c])) + // cond: isPowerOfTwo(c+1) && int32(c) >= 7 + // result: (MOVWUreg (ADDshiftLL (NEG x) x [log64(c+1)])) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x := v_0 + if v_1.Op != OpARM64MOVDconst { + continue + } + c := auxIntToInt64(v_1.AuxInt) + if !(isPowerOfTwo(c+1) && int32(c) >= 7) { + continue + } + v.reset(OpARM64MOVWUreg) + v0 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) + v0.AuxInt = int64ToAuxInt(log64(c + 1)) + v1 := b.NewValue0(v.Pos, OpARM64NEG, x.Type) + v1.AddArg(x) + v0.AddArg2(v1, x) + v.AddArg(v0) + return true + } + break + } + // match: (MULW x (MOVDconst [c])) + // cond: c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c) + // result: (MOVWUreg (SLLconst [log64(c/3)] (ADDshiftLL x x [1]))) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x := v_0 + if v_1.Op != OpARM64MOVDconst { + continue + } + c := auxIntToInt64(v_1.AuxInt) + if !(c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c)) { + continue + } + v.reset(OpARM64MOVWUreg) + v0 := b.NewValue0(v.Pos, OpARM64SLLconst, x.Type) + v0.AuxInt = int64ToAuxInt(log64(c / 3)) + v1 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) + v1.AuxInt = int64ToAuxInt(1) + v1.AddArg2(x, x) + v0.AddArg(v1) + v.AddArg(v0) + return true + } + break + } + // match: (MULW x (MOVDconst [c])) + // cond: c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c) + // result: (MOVWUreg (SLLconst [log64(c/5)] (ADDshiftLL x x [2]))) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x := v_0 + if v_1.Op != OpARM64MOVDconst { + continue + } + c := auxIntToInt64(v_1.AuxInt) + if !(c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c)) { + continue + } + v.reset(OpARM64MOVWUreg) + v0 := b.NewValue0(v.Pos, OpARM64SLLconst, x.Type) + v0.AuxInt = int64ToAuxInt(log64(c / 5)) + v1 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) + v1.AuxInt = int64ToAuxInt(2) + v1.AddArg2(x, x) + v0.AddArg(v1) + v.AddArg(v0) + return true + } + break + } + // match: (MULW x (MOVDconst [c])) + // cond: c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c) + // result: (MOVWUreg (SLLconst [log64(c/7)] (ADDshiftLL (NEG x) x [3]))) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x := v_0 + if v_1.Op != OpARM64MOVDconst { + continue + } + c := auxIntToInt64(v_1.AuxInt) + if !(c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c)) { + continue + } + v.reset(OpARM64MOVWUreg) + v0 := b.NewValue0(v.Pos, OpARM64SLLconst, x.Type) + v0.AuxInt = int64ToAuxInt(log64(c / 7)) + v1 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) + v1.AuxInt = int64ToAuxInt(3) + v2 := b.NewValue0(v.Pos, OpARM64NEG, x.Type) + v2.AddArg(x) + v1.AddArg2(v2, x) + v0.AddArg(v1) + v.AddArg(v0) + return true + } + break + } + // match: (MULW x (MOVDconst [c])) + // cond: c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c) + // result: (MOVWUreg (SLLconst [log64(c/9)] (ADDshiftLL x x [3]))) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x := v_0 + if v_1.Op != OpARM64MOVDconst { + continue + } + c := auxIntToInt64(v_1.AuxInt) + if !(c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c)) { + continue + } + v.reset(OpARM64MOVWUreg) + v0 := b.NewValue0(v.Pos, OpARM64SLLconst, x.Type) + v0.AuxInt = int64ToAuxInt(log64(c / 9)) + v1 := b.NewValue0(v.Pos, OpARM64ADDshiftLL, x.Type) + v1.AuxInt = int64ToAuxInt(3) + v1.AddArg2(x, x) + v0.AddArg(v1) + v.AddArg(v0) return true } break @@ -12699,18 +13022,6 @@ func rewriteValueARM64_OpARM64NEG(v *Value) bool { v.AddArg2(x, y) return true } - // match: (NEG (SUB x y)) - // result: (SUB y x) - for { - if v_0.Op != OpARM64SUB { - break - } - y := v_0.Args[1] - x := v_0.Args[0] - v.reset(OpARM64SUB) - v.AddArg2(y, x) - return true - } // match: (NEG (NEG x)) // result: x for { @@ -15216,18 +15527,6 @@ func rewriteValueARM64_OpARM64SUB(v *Value) bool { v.AddArg(v0) return true } - // match: (SUB x (NEG y)) - // result: (ADD x y) - for { - x := v_0 - if v_1.Op != OpARM64NEG { - break - } - y := v_1.Args[0] - v.reset(OpARM64ADD) - v.AddArg2(x, y) - return true - } // match: (SUB x x) // result: (MOVDconst [0]) for { @@ -19306,49 +19605,20 @@ func rewriteValueARM64_OpMove(v *Value) bool { v.AddArg4(dst, v0, v2, mem) return true } - // match: (Move [s] dst src mem) - // cond: s > 16 && s <= 24 - // result: (MOVDstore [int32(s-8)] dst (MOVDload [int32(s-8)] src mem) (STP dst (Select0 (LDP src mem)) (Select1 (LDP src mem)) mem)) + // match: (Move [32] dst src mem) + // result: (STP [16] dst (Select0 (LDP [16] src mem)) (Select1 (LDP [16] src mem)) (STP dst (Select0 (LDP src mem)) (Select1 (LDP src mem)) mem)) for { - s := auxIntToInt64(v.AuxInt) - dst := v_0 - src := v_1 - mem := v_2 - if !(s > 16 && s <= 24) { + if auxIntToInt64(v.AuxInt) != 32 { break } - v.reset(OpARM64MOVDstore) - v.AuxInt = int32ToAuxInt(int32(s - 8)) - v0 := b.NewValue0(v.Pos, OpARM64MOVDload, typ.UInt64) - v0.AuxInt = int32ToAuxInt(int32(s - 8)) - v0.AddArg2(src, mem) - v1 := b.NewValue0(v.Pos, OpARM64STP, types.TypeMem) - v2 := b.NewValue0(v.Pos, OpSelect0, typ.UInt64) - v3 := b.NewValue0(v.Pos, OpARM64LDP, types.NewTuple(typ.UInt64, typ.UInt64)) - v3.AddArg2(src, mem) - v2.AddArg(v3) - v4 := b.NewValue0(v.Pos, OpSelect1, typ.UInt64) - v4.AddArg(v3) - v1.AddArg4(dst, v2, v4, mem) - v.AddArg3(dst, v0, v1) - return true - } - // match: (Move [s] dst src mem) - // cond: s > 24 && s <= 32 - // result: (STP [int32(s-16)] dst (Select0 (LDP [int32(s-16)] src mem)) (Select1 (LDP [int32(s-16)] src mem)) (STP dst (Select0 (LDP src mem)) (Select1 (LDP src mem)) mem)) - for { - s := auxIntToInt64(v.AuxInt) dst := v_0 src := v_1 mem := v_2 - if !(s > 24 && s <= 32) { - break - } v.reset(OpARM64STP) - v.AuxInt = int32ToAuxInt(int32(s - 16)) + v.AuxInt = int32ToAuxInt(16) v0 := b.NewValue0(v.Pos, OpSelect0, typ.UInt64) v1 := b.NewValue0(v.Pos, OpARM64LDP, types.NewTuple(typ.UInt64, typ.UInt64)) - v1.AuxInt = int32ToAuxInt(int32(s - 16)) + v1.AuxInt = int32ToAuxInt(16) v1.AddArg2(src, mem) v0.AddArg(v1) v2 := b.NewValue0(v.Pos, OpSelect1, typ.UInt64) @@ -19364,59 +19634,20 @@ func rewriteValueARM64_OpMove(v *Value) bool { v.AddArg4(dst, v0, v2, v3) return true } - // match: (Move [s] dst src mem) - // cond: s > 32 && s <= 40 - // result: (MOVDstore [int32(s-8)] dst (MOVDload [int32(s-8)] src mem) (STP [16] dst (Select0 (LDP [16] src mem)) (Select1 (LDP [16] src mem)) (STP dst (Select0 (LDP src mem)) (Select1 (LDP src mem)) mem))) + // match: (Move [48] dst src mem) + // result: (STP [32] dst (Select0 (LDP [32] src mem)) (Select1 (LDP [32] src mem)) (STP [16] dst (Select0 (LDP [16] src mem)) (Select1 (LDP [16] src mem)) (STP dst (Select0 (LDP src mem)) (Select1 (LDP src mem)) mem))) for { - s := auxIntToInt64(v.AuxInt) - dst := v_0 - src := v_1 - mem := v_2 - if !(s > 32 && s <= 40) { + if auxIntToInt64(v.AuxInt) != 48 { break } - v.reset(OpARM64MOVDstore) - v.AuxInt = int32ToAuxInt(int32(s - 8)) - v0 := b.NewValue0(v.Pos, OpARM64MOVDload, typ.UInt64) - v0.AuxInt = int32ToAuxInt(int32(s - 8)) - v0.AddArg2(src, mem) - v1 := b.NewValue0(v.Pos, OpARM64STP, types.TypeMem) - v1.AuxInt = int32ToAuxInt(16) - v2 := b.NewValue0(v.Pos, OpSelect0, typ.UInt64) - v3 := b.NewValue0(v.Pos, OpARM64LDP, types.NewTuple(typ.UInt64, typ.UInt64)) - v3.AuxInt = int32ToAuxInt(16) - v3.AddArg2(src, mem) - v2.AddArg(v3) - v4 := b.NewValue0(v.Pos, OpSelect1, typ.UInt64) - v4.AddArg(v3) - v5 := b.NewValue0(v.Pos, OpARM64STP, types.TypeMem) - v6 := b.NewValue0(v.Pos, OpSelect0, typ.UInt64) - v7 := b.NewValue0(v.Pos, OpARM64LDP, types.NewTuple(typ.UInt64, typ.UInt64)) - v7.AddArg2(src, mem) - v6.AddArg(v7) - v8 := b.NewValue0(v.Pos, OpSelect1, typ.UInt64) - v8.AddArg(v7) - v5.AddArg4(dst, v6, v8, mem) - v1.AddArg4(dst, v2, v4, v5) - v.AddArg3(dst, v0, v1) - return true - } - // match: (Move [s] dst src mem) - // cond: s > 40 && s <= 48 - // result: (STP [int32(s-16)] dst (Select0 (LDP [int32(s-16)] src mem)) (Select1 (LDP [int32(s-16)] src mem)) (STP [16] dst (Select0 (LDP [16] src mem)) (Select1 (LDP [16] src mem)) (STP dst (Select0 (LDP src mem)) (Select1 (LDP src mem)) mem))) - for { - s := auxIntToInt64(v.AuxInt) dst := v_0 src := v_1 mem := v_2 - if !(s > 40 && s <= 48) { - break - } v.reset(OpARM64STP) - v.AuxInt = int32ToAuxInt(int32(s - 16)) + v.AuxInt = int32ToAuxInt(32) v0 := b.NewValue0(v.Pos, OpSelect0, typ.UInt64) v1 := b.NewValue0(v.Pos, OpARM64LDP, types.NewTuple(typ.UInt64, typ.UInt64)) - v1.AuxInt = int32ToAuxInt(int32(s - 16)) + v1.AuxInt = int32ToAuxInt(32) v1.AddArg2(src, mem) v0.AddArg(v1) v2 := b.NewValue0(v.Pos, OpSelect1, typ.UInt64) @@ -19442,69 +19673,20 @@ func rewriteValueARM64_OpMove(v *Value) bool { v.AddArg4(dst, v0, v2, v3) return true } - // match: (Move [s] dst src mem) - // cond: s > 48 && s <= 56 - // result: (MOVDstore [int32(s-8)] dst (MOVDload [int32(s-8)] src mem) (STP [32] dst (Select0 (LDP [32] src mem)) (Select1 (LDP [32] src mem)) (STP [16] dst (Select0 (LDP [16] src mem)) (Select1 (LDP [16] src mem)) (STP dst (Select0 (LDP src mem)) (Select1 (LDP src mem)) mem)))) + // match: (Move [64] dst src mem) + // result: (STP [48] dst (Select0 (LDP [48] src mem)) (Select1 (LDP [48] src mem)) (STP [32] dst (Select0 (LDP [32] src mem)) (Select1 (LDP [32] src mem)) (STP [16] dst (Select0 (LDP [16] src mem)) (Select1 (LDP [16] src mem)) (STP dst (Select0 (LDP src mem)) (Select1 (LDP src mem)) mem)))) for { - s := auxIntToInt64(v.AuxInt) - dst := v_0 - src := v_1 - mem := v_2 - if !(s > 48 && s <= 56) { + if auxIntToInt64(v.AuxInt) != 64 { break } - v.reset(OpARM64MOVDstore) - v.AuxInt = int32ToAuxInt(int32(s - 8)) - v0 := b.NewValue0(v.Pos, OpARM64MOVDload, typ.UInt64) - v0.AuxInt = int32ToAuxInt(int32(s - 8)) - v0.AddArg2(src, mem) - v1 := b.NewValue0(v.Pos, OpARM64STP, types.TypeMem) - v1.AuxInt = int32ToAuxInt(32) - v2 := b.NewValue0(v.Pos, OpSelect0, typ.UInt64) - v3 := b.NewValue0(v.Pos, OpARM64LDP, types.NewTuple(typ.UInt64, typ.UInt64)) - v3.AuxInt = int32ToAuxInt(32) - v3.AddArg2(src, mem) - v2.AddArg(v3) - v4 := b.NewValue0(v.Pos, OpSelect1, typ.UInt64) - v4.AddArg(v3) - v5 := b.NewValue0(v.Pos, OpARM64STP, types.TypeMem) - v5.AuxInt = int32ToAuxInt(16) - v6 := b.NewValue0(v.Pos, OpSelect0, typ.UInt64) - v7 := b.NewValue0(v.Pos, OpARM64LDP, types.NewTuple(typ.UInt64, typ.UInt64)) - v7.AuxInt = int32ToAuxInt(16) - v7.AddArg2(src, mem) - v6.AddArg(v7) - v8 := b.NewValue0(v.Pos, OpSelect1, typ.UInt64) - v8.AddArg(v7) - v9 := b.NewValue0(v.Pos, OpARM64STP, types.TypeMem) - v10 := b.NewValue0(v.Pos, OpSelect0, typ.UInt64) - v11 := b.NewValue0(v.Pos, OpARM64LDP, types.NewTuple(typ.UInt64, typ.UInt64)) - v11.AddArg2(src, mem) - v10.AddArg(v11) - v12 := b.NewValue0(v.Pos, OpSelect1, typ.UInt64) - v12.AddArg(v11) - v9.AddArg4(dst, v10, v12, mem) - v5.AddArg4(dst, v6, v8, v9) - v1.AddArg4(dst, v2, v4, v5) - v.AddArg3(dst, v0, v1) - return true - } - // match: (Move [s] dst src mem) - // cond: s > 56 && s <= 64 - // result: (STP [int32(s-16)] dst (Select0 (LDP [int32(s-16)] src mem)) (Select1 (LDP [int32(s-16)] src mem)) (STP [32] dst (Select0 (LDP [32] src mem)) (Select1 (LDP [32] src mem)) (STP [16] dst (Select0 (LDP [16] src mem)) (Select1 (LDP [16] src mem)) (STP dst (Select0 (LDP src mem)) (Select1 (LDP src mem)) mem)))) - for { - s := auxIntToInt64(v.AuxInt) dst := v_0 src := v_1 mem := v_2 - if !(s > 56 && s <= 64) { - break - } v.reset(OpARM64STP) - v.AuxInt = int32ToAuxInt(int32(s - 16)) + v.AuxInt = int32ToAuxInt(48) v0 := b.NewValue0(v.Pos, OpSelect0, typ.UInt64) v1 := b.NewValue0(v.Pos, OpARM64LDP, types.NewTuple(typ.UInt64, typ.UInt64)) - v1.AuxInt = int32ToAuxInt(int32(s - 16)) + v1.AuxInt = int32ToAuxInt(48) v1.AddArg2(src, mem) v0.AddArg(v1) v2 := b.NewValue0(v.Pos, OpSelect1, typ.UInt64) @@ -19541,14 +19723,14 @@ func rewriteValueARM64_OpMove(v *Value) bool { return true } // match: (Move [s] dst src mem) - // cond: s%16 != 0 && s%16 <= 8 && s > 64 + // cond: s%16 != 0 && s%16 <= 8 && s > 16 // result: (Move [8] (OffPtr dst [s-8]) (OffPtr src [s-8]) (Move [s-s%16] dst src mem)) for { s := auxIntToInt64(v.AuxInt) dst := v_0 src := v_1 mem := v_2 - if !(s%16 != 0 && s%16 <= 8 && s > 64) { + if !(s%16 != 0 && s%16 <= 8 && s > 16) { break } v.reset(OpMove) @@ -19566,14 +19748,14 @@ func rewriteValueARM64_OpMove(v *Value) bool { return true } // match: (Move [s] dst src mem) - // cond: s%16 != 0 && s%16 > 8 && s > 64 + // cond: s%16 != 0 && s%16 > 8 && s > 16 // result: (Move [16] (OffPtr dst [s-16]) (OffPtr src [s-16]) (Move [s-s%16] dst src mem)) for { s := auxIntToInt64(v.AuxInt) dst := v_0 src := v_1 mem := v_2 - if !(s%16 != 0 && s%16 > 8 && s > 64) { + if !(s%16 != 0 && s%16 > 8 && s > 16) { break } v.reset(OpMove) diff --git a/src/cmd/compile/internal/ssa/rewriteARM64latelower.go b/src/cmd/compile/internal/ssa/rewriteARM64latelower.go index 0fa5e26e93d0f9..3defeba4c5801a 100644 --- a/src/cmd/compile/internal/ssa/rewriteARM64latelower.go +++ b/src/cmd/compile/internal/ssa/rewriteARM64latelower.go @@ -38,8 +38,6 @@ func rewriteValueARM64latelower(v *Value) bool { return rewriteValueARM64latelower_OpARM64MOVWreg(v) case OpARM64ORconst: return rewriteValueARM64latelower_OpARM64ORconst(v) - case OpARM64SLLconst: - return rewriteValueARM64latelower_OpARM64SLLconst(v) case OpARM64SUBconst: return rewriteValueARM64latelower_OpARM64SUBconst(v) case OpARM64TSTWconst: @@ -998,21 +996,6 @@ func rewriteValueARM64latelower_OpARM64ORconst(v *Value) bool { } return false } -func rewriteValueARM64latelower_OpARM64SLLconst(v *Value) bool { - v_0 := v.Args[0] - // match: (SLLconst [1] x) - // result: (ADD x x) - for { - if auxIntToInt64(v.AuxInt) != 1 { - break - } - x := v_0 - v.reset(OpARM64ADD) - v.AddArg2(x, x) - return true - } - return false -} func rewriteValueARM64latelower_OpARM64SUBconst(v *Value) bool { v_0 := v.Args[0] b := v.Block diff --git a/src/cmd/compile/internal/ssa/rewriteLOONG64.go b/src/cmd/compile/internal/ssa/rewriteLOONG64.go index 7c46ed77272ad0..ea6aee82505958 100644 --- a/src/cmd/compile/internal/ssa/rewriteLOONG64.go +++ b/src/cmd/compile/internal/ssa/rewriteLOONG64.go @@ -436,8 +436,6 @@ func rewriteValueLOONG64(v *Value) bool { return rewriteValueLOONG64_OpLOONG64NORconst(v) case OpLOONG64OR: return rewriteValueLOONG64_OpLOONG64OR(v) - case OpLOONG64ORN: - return rewriteValueLOONG64_OpLOONG64ORN(v) case OpLOONG64ORconst: return rewriteValueLOONG64_OpLOONG64ORconst(v) case OpLOONG64REMV: @@ -676,10 +674,6 @@ func rewriteValueLOONG64(v *Value) bool { return rewriteValueLOONG64_OpPopCount32(v) case OpPopCount64: return rewriteValueLOONG64_OpPopCount64(v) - case OpPrefetchCache: - return rewriteValueLOONG64_OpPrefetchCache(v) - case OpPrefetchCacheStreamed: - return rewriteValueLOONG64_OpPrefetchCacheStreamed(v) case OpPubBarrier: v.Op = OpLOONG64LoweredPubBarrier return true @@ -1928,21 +1922,6 @@ func rewriteValueLOONG64_OpLOONG64AND(v *Value) bool { v.copyOf(x) return true } - // match: (AND x (NORconst [0] y)) - // result: (ANDN x y) - for { - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - x := v_0 - if v_1.Op != OpLOONG64NORconst || auxIntToInt64(v_1.AuxInt) != 0 { - continue - } - y := v_1.Args[0] - v.reset(OpLOONG64ANDN) - v.AddArg2(x, y) - return true - } - break - } return false } func rewriteValueLOONG64_OpLOONG64ANDconst(v *Value) bool { @@ -5442,77 +5421,6 @@ func rewriteValueLOONG64_OpLOONG64MULV(v *Value) bool { } func rewriteValueLOONG64_OpLOONG64NEGV(v *Value) bool { v_0 := v.Args[0] - b := v.Block - // match: (NEGV (SUBV x y)) - // result: (SUBV y x) - for { - if v_0.Op != OpLOONG64SUBV { - break - } - y := v_0.Args[1] - x := v_0.Args[0] - v.reset(OpLOONG64SUBV) - v.AddArg2(y, x) - return true - } - // match: (NEGV s:(ADDVconst [c] (SUBV x y))) - // cond: s.Uses == 1 && is12Bit(-c) - // result: (ADDVconst [-c] (SUBV y x)) - for { - t := v.Type - s := v_0 - if s.Op != OpLOONG64ADDVconst { - break - } - c := auxIntToInt64(s.AuxInt) - s_0 := s.Args[0] - if s_0.Op != OpLOONG64SUBV { - break - } - y := s_0.Args[1] - x := s_0.Args[0] - if !(s.Uses == 1 && is12Bit(-c)) { - break - } - v.reset(OpLOONG64ADDVconst) - v.AuxInt = int64ToAuxInt(-c) - v0 := b.NewValue0(v.Pos, OpLOONG64SUBV, t) - v0.AddArg2(y, x) - v.AddArg(v0) - return true - } - // match: (NEGV (NEGV x)) - // result: x - for { - if v_0.Op != OpLOONG64NEGV { - break - } - x := v_0.Args[0] - v.copyOf(x) - return true - } - // match: (NEGV s:(ADDVconst [c] (NEGV x))) - // cond: s.Uses == 1 && is12Bit(-c) - // result: (ADDVconst [-c] x) - for { - s := v_0 - if s.Op != OpLOONG64ADDVconst { - break - } - c := auxIntToInt64(s.AuxInt) - s_0 := s.Args[0] - if s_0.Op != OpLOONG64NEGV { - break - } - x := s_0.Args[0] - if !(s.Uses == 1 && is12Bit(-c)) { - break - } - v.reset(OpLOONG64ADDVconst) - v.AuxInt = int64ToAuxInt(-c) - v.AddArg(x) - return true - } // match: (NEGV (MOVVconst [c])) // result: (MOVVconst [-c]) for { @@ -5600,36 +5508,6 @@ func rewriteValueLOONG64_OpLOONG64OR(v *Value) bool { v.copyOf(x) return true } - // match: (OR x (NORconst [0] y)) - // result: (ORN x y) - for { - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - x := v_0 - if v_1.Op != OpLOONG64NORconst || auxIntToInt64(v_1.AuxInt) != 0 { - continue - } - y := v_1.Args[0] - v.reset(OpLOONG64ORN) - v.AddArg2(x, y) - return true - } - break - } - return false -} -func rewriteValueLOONG64_OpLOONG64ORN(v *Value) bool { - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (ORN x (MOVVconst [-1])) - // result: x - for { - x := v_0 - if v_1.Op != OpLOONG64MOVVconst || auxIntToInt64(v_1.AuxInt) != -1 { - break - } - v.copyOf(x) - return true - } return false } func rewriteValueLOONG64_OpLOONG64ORconst(v *Value) bool { @@ -6883,18 +6761,6 @@ func rewriteValueLOONG64_OpLOONG64SUBV(v *Value) bool { v.AddArg(x) return true } - // match: (SUBV x (NEGV y)) - // result: (ADDV x y) - for { - x := v_0 - if v_1.Op != OpLOONG64NEGV { - break - } - y := v_1.Args[0] - v.reset(OpLOONG64ADDV) - v.AddArg2(x, y) - return true - } // match: (SUBV x x) // result: (MOVVconst [0]) for { @@ -9129,34 +8995,6 @@ func rewriteValueLOONG64_OpPopCount64(v *Value) bool { return true } } -func rewriteValueLOONG64_OpPrefetchCache(v *Value) bool { - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (PrefetchCache addr mem) - // result: (PRELD addr mem [0]) - for { - addr := v_0 - mem := v_1 - v.reset(OpLOONG64PRELD) - v.AuxInt = int64ToAuxInt(0) - v.AddArg2(addr, mem) - return true - } -} -func rewriteValueLOONG64_OpPrefetchCacheStreamed(v *Value) bool { - v_1 := v.Args[1] - v_0 := v.Args[0] - // match: (PrefetchCacheStreamed addr mem) - // result: (PRELDX addr mem [(((512 << 1) + (1 << 12)) << 5) + 2]) - for { - addr := v_0 - mem := v_1 - v.reset(OpLOONG64PRELDX) - v.AuxInt = int64ToAuxInt((((512 << 1) + (1 << 12)) << 5) + 2) - v.AddArg2(addr, mem) - return true - } -} func rewriteValueLOONG64_OpRotateLeft16(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] diff --git a/src/cmd/compile/internal/ssa/rewriteMIPS.go b/src/cmd/compile/internal/ssa/rewriteMIPS.go index 4c5edb8694d284..1bc2cb6e6da993 100644 --- a/src/cmd/compile/internal/ssa/rewriteMIPS.go +++ b/src/cmd/compile/internal/ssa/rewriteMIPS.go @@ -450,9 +450,6 @@ func rewriteValueMIPS(v *Value) bool { return rewriteValueMIPS_OpPanicBounds(v) case OpPanicExtend: return rewriteValueMIPS_OpPanicExtend(v) - case OpPubBarrier: - v.Op = OpMIPSLoweredPubBarrier - return true case OpRotateLeft16: return rewriteValueMIPS_OpRotateLeft16(v) case OpRotateLeft32: @@ -4099,28 +4096,6 @@ func rewriteValueMIPS_OpMIPSMUL(v *Value) bool { } func rewriteValueMIPS_OpMIPSNEG(v *Value) bool { v_0 := v.Args[0] - // match: (NEG (SUB x y)) - // result: (SUB y x) - for { - if v_0.Op != OpMIPSSUB { - break - } - y := v_0.Args[1] - x := v_0.Args[0] - v.reset(OpMIPSSUB) - v.AddArg2(y, x) - return true - } - // match: (NEG (NEG x)) - // result: x - for { - if v_0.Op != OpMIPSNEG { - break - } - x := v_0.Args[0] - v.copyOf(x) - return true - } // match: (NEG (MOVWconst [c])) // result: (MOVWconst [-c]) for { @@ -4773,18 +4748,6 @@ func rewriteValueMIPS_OpMIPSSUB(v *Value) bool { v.AddArg(x) return true } - // match: (SUB x (NEG y)) - // result: (ADD x y) - for { - x := v_0 - if v_1.Op != OpMIPSNEG { - break - } - y := v_1.Args[0] - v.reset(OpMIPSADD) - v.AddArg2(x, y) - return true - } // match: (SUB x x) // result: (MOVWconst [0]) for { diff --git a/src/cmd/compile/internal/ssa/rewriteMIPS64.go b/src/cmd/compile/internal/ssa/rewriteMIPS64.go index c30815cefb5b99..10281e7e70905a 100644 --- a/src/cmd/compile/internal/ssa/rewriteMIPS64.go +++ b/src/cmd/compile/internal/ssa/rewriteMIPS64.go @@ -502,9 +502,6 @@ func rewriteValueMIPS64(v *Value) bool { return true case OpPanicBounds: return rewriteValueMIPS64_OpPanicBounds(v) - case OpPubBarrier: - v.Op = OpMIPS64LoweredPubBarrier - return true case OpRotateLeft16: return rewriteValueMIPS64_OpRotateLeft16(v) case OpRotateLeft32: @@ -4676,28 +4673,6 @@ func rewriteValueMIPS64_OpMIPS64MOVWstorezero(v *Value) bool { } func rewriteValueMIPS64_OpMIPS64NEGV(v *Value) bool { v_0 := v.Args[0] - // match: (NEGV (SUBV x y)) - // result: (SUBV y x) - for { - if v_0.Op != OpMIPS64SUBV { - break - } - y := v_0.Args[1] - x := v_0.Args[0] - v.reset(OpMIPS64SUBV) - v.AddArg2(y, x) - return true - } - // match: (NEGV (NEGV x)) - // result: x - for { - if v_0.Op != OpMIPS64NEGV { - break - } - x := v_0.Args[0] - v.copyOf(x) - return true - } // match: (NEGV (MOVVconst [c])) // result: (MOVVconst [-c]) for { @@ -5344,18 +5319,6 @@ func rewriteValueMIPS64_OpMIPS64SUBV(v *Value) bool { v.AddArg(x) return true } - // match: (SUBV x (NEGV y)) - // result: (ADDV x y) - for { - x := v_0 - if v_1.Op != OpMIPS64NEGV { - break - } - y := v_1.Args[0] - v.reset(OpMIPS64ADDV) - v.AddArg2(x, y) - return true - } // match: (SUBV x x) // result: (MOVVconst [0]) for { diff --git a/src/cmd/compile/internal/ssa/rewriteRISCV64.go b/src/cmd/compile/internal/ssa/rewriteRISCV64.go index 95c6489a511be8..182ca2d3fd674f 100644 --- a/src/cmd/compile/internal/ssa/rewriteRISCV64.go +++ b/src/cmd/compile/internal/ssa/rewriteRISCV64.go @@ -110,13 +110,6 @@ func rewriteValueRISCV64(v *Value) bool { return rewriteValueRISCV64_OpBitLen64(v) case OpBitLen8: return rewriteValueRISCV64_OpBitLen8(v) - case OpBswap16: - return rewriteValueRISCV64_OpBswap16(v) - case OpBswap32: - return rewriteValueRISCV64_OpBswap32(v) - case OpBswap64: - v.Op = OpRISCV64REV8 - return true case OpClosureCall: v.Op = OpRISCV64CALLclosure return true @@ -487,16 +480,6 @@ func rewriteValueRISCV64(v *Value) bool { return true case OpPanicBounds: return rewriteValueRISCV64_OpPanicBounds(v) - case OpPopCount16: - return rewriteValueRISCV64_OpPopCount16(v) - case OpPopCount32: - v.Op = OpRISCV64CPOPW - return true - case OpPopCount64: - v.Op = OpRISCV64CPOP - return true - case OpPopCount8: - return rewriteValueRISCV64_OpPopCount8(v) case OpPubBarrier: v.Op = OpRISCV64LoweredPubBarrier return true @@ -586,8 +569,6 @@ func rewriteValueRISCV64(v *Value) bool { return rewriteValueRISCV64_OpRISCV64OR(v) case OpRISCV64ORI: return rewriteValueRISCV64_OpRISCV64ORI(v) - case OpRISCV64ORN: - return rewriteValueRISCV64_OpRISCV64ORN(v) case OpRISCV64ROL: return rewriteValueRISCV64_OpRISCV64ROL(v) case OpRISCV64ROLW: @@ -1021,38 +1002,6 @@ func rewriteValueRISCV64_OpBitLen8(v *Value) bool { return true } } -func rewriteValueRISCV64_OpBswap16(v *Value) bool { - v_0 := v.Args[0] - b := v.Block - // match: (Bswap16 x) - // result: (SRLI [48] (REV8 x)) - for { - t := v.Type - x := v_0 - v.reset(OpRISCV64SRLI) - v.AuxInt = int64ToAuxInt(48) - v0 := b.NewValue0(v.Pos, OpRISCV64REV8, t) - v0.AddArg(x) - v.AddArg(v0) - return true - } -} -func rewriteValueRISCV64_OpBswap32(v *Value) bool { - v_0 := v.Args[0] - b := v.Block - // match: (Bswap32