]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.simd] simd/_gen/simdgen: parse memory operands
authorJunyang Shao <shaojunyang@google.com>
Wed, 3 Sep 2025 17:17:55 +0000 (17:17 +0000)
committerJunyang Shao <shaojunyang@google.com>
Sat, 6 Sep 2025 20:46:36 +0000 (13:46 -0700)
This CL has no change in the generated code.

Change-Id: Iacb65b9b401503b8b44dd19d5f4cbced862572d3
Reviewed-on: https://go-review.googlesource.com/c/go/+/700675
Reviewed-by: David Chase <drchase@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>

src/simd/_gen/simdgen/xed.go

index d749f433e37792caf3b0a8c784e6f95c856f159f..e12f41f958d63d79e80b806b7671e569fecac0c3 100644 (file)
@@ -14,9 +14,10 @@ import (
        "strconv"
        "strings"
 
+       "simd/_gen/unify"
+
        "golang.org/x/arch/x86/xeddata"
        "gopkg.in/yaml.v3"
-       "simd/_gen/unify"
 )
 
 const (
@@ -160,7 +161,13 @@ type operandAction struct {
 
 type operandMem struct {
        operandCommon
-       // TODO
+       vecShape
+       elemBaseType scalarBaseType
+       // The following fields are not flushed to the final output
+       // Supports full-vector broadcasting; implies the operand having a "vv"(vector vector) type specified in width and
+       // the instruction is with attribute TXT=BCASTSTR.
+       vbcst   bool
+       unknown bool // unknown kind
 }
 
 type vecShape struct {
@@ -217,8 +224,19 @@ func (o operandCommon) common() operandCommon {
 }
 
 func (o operandMem) addToDef(b *unify.DefBuilder) {
-       // TODO: w, base
        b.Add("class", strVal("memory"))
+       if o.unknown {
+               return
+       }
+       baseDomain, err := unify.NewStringRegex(o.elemBaseType.regex())
+       if err != nil {
+               panic("parsing baseRe: " + err.Error())
+       }
+       b.Add("base", unify.NewValue(baseDomain))
+       b.Add("bits", strVal(o.bits))
+       if o.elemBits != o.bits {
+               b.Add("elemBits", strVal(o.elemBits))
+       }
 }
 
 func (o operandVReg) addToDef(b *unify.DefBuilder) {
@@ -301,9 +319,33 @@ func decodeOperand(db *xeddata.Database, operand string) (operand, error) {
 
        lhs := op.NameLHS()
        if strings.HasPrefix(lhs, "MEM") {
-               // TODO: Width, base type
+               // looks like XED data has an inconsistency on VPADDD, marking attribute
+               // VPBROADCASTD instead of the canonical BCASTSTR.
+               if op.Width == "vv" && (op.Attributes["TXT=BCASTSTR"] ||
+                       op.Attributes["TXT=VPBROADCASTD"]) {
+                       baseType, elemBits, ok := decodeType(op)
+                       if !ok {
+                               return nil, fmt.Errorf("failed to decode memory width %q", operand)
+                       }
+                       // This operand has two possible width([bits]):
+                       // 1. the same as the other operands
+                       // 2. the element width as the other operands (broaccasting)
+                       // left it default to 2, later we will set a new field in the operation
+                       // to indicate this dual-width property.
+                       shape := vecShape{elemBits: elemBits, bits: elemBits}
+                       return operandMem{
+                               operandCommon: common,
+                               vecShape:      shape,
+                               elemBaseType:  baseType,
+                               vbcst:         true,
+                               unknown:       false,
+                       }, nil
+               }
+               // TODO: parse op.Width better to handle all cases
+               // Right now this will at least miss VPBROADCAST.
                return operandMem{
                        operandCommon: common,
+                       unknown:       true,
                }, nil
        } else if strings.HasPrefix(lhs, "REG") {
                if op.Width == "mskw" {
@@ -516,6 +558,35 @@ func addOperandsToDef(ops []operand, instDB *unify.DefBuilder, variant instVaria
        instDB.Add("in", unify.NewValue(unify.NewTuple(inVals...)))
        instDB.Add("inVariant", unify.NewValue(unify.NewTuple(inVar...)))
        instDB.Add("out", unify.NewValue(unify.NewTuple(outVals...)))
+       instDB.Add("mem", unify.NewValue(unify.NewStringExact(checkMem(ops))))
+}
+
+// checkMem checks the shapes of memory operand in the instruction and returns the shape.
+// Keep this function in sync with [decodeOperand].
+func checkMem(ops []operand) string {
+       memState := "noMem"
+       var mem *operandMem
+       memCnt := 0
+       for _, op := range ops {
+               if m, ok := op.(operandMem); ok {
+                       mem = &m
+                       memCnt++
+               }
+       }
+       if mem != nil {
+               if mem.unknown {
+                       memState = "unknown"
+               } else if memCnt > 1 {
+                       memState = "tooManyMem"
+               } else {
+                       // We only have vbcst case as of now.
+                       // This shape has an indication that [bits] fields has two possible value:
+                       // 1. The element broadcast width, which is its peer vreg operand's [elemBits] (default val in the parsed XED data)
+                       // 2. The full vector width, which is its peer vreg operand's [bits] (godefs should be aware of this)
+                       memState = "vbcst"
+               }
+       }
+       return memState
 }
 
 func instToUVal(inst *xeddata.Inst, ops []operand) []*unify.Value {