internal/simdgen: introduce instruction variants and use for masked ops In AVX-512, nearly all operations take a mask, but it's optional. Currently, the XED loader produces only the masked form of these instructions. Since this mask is one of the input operands, the Go definitions YAML needs a separate entry to match the masked form. To generate both the masked and unmasked forms, we unify only the masked form and then when generating the Go API we recognize this and duplicate the operation in unmasked form. Unfortunately, since pre-AVX-512 operations never have this mask input, we wind up duplicating many unifier definitions to match both the pre-AVX-512 and AVX-512 forms, even though the unmasked operation produced during API generation looks like a pre-AVX-512 definition. To fix all this, we flip things around. Instead of generating the masked and unmasked variants at API generation, we generate them much earlier, during XED loading. The XED data already contains a clear marker for which masks are optional (it's wrong in a few cases, which we work around). For instructions with an optional mask, the XED loader now generates both the masked and unmasked forms. Then, to make both easy to match, we put the mask operand into a new top-level tuple called "inVariant". This way, a single unifier def can match the pre-AVX-512 instruction, and the masked and unmasked AVX-512 instructions. When we load the results of unification for generating the API, we do some light canonicalization of the operation. We append any inVariant operands to the input operands list; and if there's a mask in inVariant, we append "Masked" to the Go method name. With all of this done, we can delete all of the "*Masked" forms of operations from the YAML. In a few cases, we have to merge some information from the masked form into the unmasked form. For operations that were introduced in AVX-512, we currently *only* have the Masked form; so for these we keep the definition but strip out the masking. This ultimately has very little effect on the generated API. In a few cases it fills in holes that let us pick a better instruction. It fixes some doc strings that got duplicated incorrectly between masked and unmasked forms. This change makes it much easier to write other tools besides the Go API generator because it moves nearly all masking logic out of writeGoDefs. It also eliminates some fragile Operation duplication logic from writeGoDefs. I plan to move a few more things out of the Go API generator, but this is definitely the big one. Change-Id: I17ee70cff15a80e8025eec96a7286266233546d9 Reviewed-on: https://go-review.googlesource.com/c/arch/+/691341 Auto-Submit: Austin Clements <austin@google.com> Reviewed-by: David Chase <drchase@google.com> Reviewed-by: Junyang Shao <shaojunyang@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This repository holds machine architecture information used by the Go toolchain. The parts needed in the main Go repository are copied in.
This repository uses Gerrit for code changes. To learn how to submit changes to this repository, see https://go.dev/doc/contribute.
The git repository is https://go.googlesource.com/arch.
The main issue tracker for the arch repository is located at https://go.dev/issues. Prefix your issue with “x/arch:” in the subject line, so it is easy to find.