From f42c9261d35d567ebb63580b2a9f03301e58c5d8 Mon Sep 17 00:00:00 2001 From: Junyang Shao Date: Wed, 3 Sep 2025 17:17:55 +0000 Subject: [PATCH] [dev.simd] simd/_gen/simdgen: parse memory operands 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 LUCI-TryBot-Result: Go LUCI --- src/simd/_gen/simdgen/xed.go | 79 ++++++++++++++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 4 deletions(-) diff --git a/src/simd/_gen/simdgen/xed.go b/src/simd/_gen/simdgen/xed.go index d749f433e3..e12f41f958 100644 --- a/src/simd/_gen/simdgen/xed.go +++ b/src/simd/_gen/simdgen/xed.go @@ -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 { -- 2.52.0