mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[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 <drchase@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
parent
356c48d8e9
commit
f42c9261d3
1 changed files with 75 additions and 4 deletions
|
|
@ -14,9 +14,10 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"simd/_gen/unify"
|
||||||
|
|
||||||
"golang.org/x/arch/x86/xeddata"
|
"golang.org/x/arch/x86/xeddata"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
"simd/_gen/unify"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -160,7 +161,13 @@ type operandAction struct {
|
||||||
|
|
||||||
type operandMem struct {
|
type operandMem struct {
|
||||||
operandCommon
|
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 {
|
type vecShape struct {
|
||||||
|
|
@ -217,8 +224,19 @@ func (o operandCommon) common() operandCommon {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o operandMem) addToDef(b *unify.DefBuilder) {
|
func (o operandMem) addToDef(b *unify.DefBuilder) {
|
||||||
// TODO: w, base
|
|
||||||
b.Add("class", strVal("memory"))
|
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) {
|
func (o operandVReg) addToDef(b *unify.DefBuilder) {
|
||||||
|
|
@ -301,9 +319,33 @@ func decodeOperand(db *xeddata.Database, operand string) (operand, error) {
|
||||||
|
|
||||||
lhs := op.NameLHS()
|
lhs := op.NameLHS()
|
||||||
if strings.HasPrefix(lhs, "MEM") {
|
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{
|
return operandMem{
|
||||||
operandCommon: common,
|
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
|
}, nil
|
||||||
} else if strings.HasPrefix(lhs, "REG") {
|
} else if strings.HasPrefix(lhs, "REG") {
|
||||||
if op.Width == "mskw" {
|
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("in", unify.NewValue(unify.NewTuple(inVals...)))
|
||||||
instDB.Add("inVariant", unify.NewValue(unify.NewTuple(inVar...)))
|
instDB.Add("inVariant", unify.NewValue(unify.NewTuple(inVar...)))
|
||||||
instDB.Add("out", unify.NewValue(unify.NewTuple(outVals...)))
|
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 {
|
func instToUVal(inst *xeddata.Inst, ops []operand) []*unify.Value {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue