1
2
3
4
5 package sve
6
7 import (
8 "fmt"
9 "sort"
10 "strings"
11
12 "simd/archsimd/_gen/unify"
13 )
14
15
16
17
18
19
20
21
22
23 func (inst *Instruction) classify() (defs []*unify.Value, reason string, anomaly bool) {
24 if !inst.isSVE() {
25 return nil, "not an SVE instruction", false
26 }
27 if inst.isAlias() {
28 return nil, "alias", false
29 }
30 allEncOps := inst.allEncodingOperands()
31 if len(allEncOps) == 0 {
32
33
34 return nil, "no operands (deferred)", false
35 }
36
37
38
39
40 var skip string
41 for _, ops := range allEncOps {
42 d, r, a := inst.classifyOperands(ops)
43 if a {
44 return nil, r, true
45 }
46 if len(d) == 0 {
47 if skip == "" {
48 skip = r
49 }
50 continue
51 }
52 defs = append(defs, d...)
53 }
54 if len(defs) == 0 {
55 return nil, skip, false
56 }
57 return defs, "", false
58 }
59
60
61 func (inst *Instruction) classifyOperands(ops []Operand) (defs []*unify.Value, reason string, anomaly bool) {
62
63 for _, op := range ops {
64 if op.Class == "unknown" {
65 return nil, fmt.Sprintf("unknown operand %q", op.Raw), true
66 }
67 }
68
69
70
71 if hasClass(ops, "reglist") {
72 return nil, "register list (deferred, TODO)", false
73 }
74
75
76
77 for _, link := range arngLinks(ops) {
78 if len(inst.resolveArrangementTable(link)) == 0 {
79 return nil, fmt.Sprintf("arrangement %q resolves to empty domain", link), true
80 }
81 }
82
83 defs = inst.emitVariants(ops)
84 if len(defs) == 0 {
85 return nil, "no defs emitted (all rows reserved/filtered)", false
86 }
87 return defs, "", false
88 }
89
90
91 type report struct {
92 Total int
93 Emitted int
94 Defs int
95 Reasons map[string]int
96
97
98 Anomalies []string
99 }
100
101
102
103
104 func analyze(path string) (*report, error) {
105 insts, err := parseInstructions(path)
106 if err != nil {
107 return nil, err
108 }
109 r := &report{Reasons: map[string]int{}}
110 for _, inst := range insts {
111 r.Total++
112 defs, reason, anomaly := inst.classify()
113 key := reason
114 if key == "" {
115 key = "emitted"
116 r.Emitted++
117 r.Defs += len(defs)
118 }
119 r.Reasons[key]++
120 if anomaly {
121 r.Anomalies = append(r.Anomalies,
122 fmt.Sprintf("%s (%s): %s", inst.mnemonic(), inst.Title, reason))
123 }
124 }
125 sort.Strings(r.Anomalies)
126 return r, nil
127 }
128
129
130 func (r *report) String() string {
131 var b strings.Builder
132 fmt.Fprintf(&b, "SVE instructions: %d (%d emitted -> %d defs)\n", r.Total, r.Emitted, r.Defs)
133 fmt.Fprintf(&b, "disposition:\n")
134 keys := make([]string, 0, len(r.Reasons))
135 for k := range r.Reasons {
136 keys = append(keys, k)
137 }
138 sort.Slice(keys, func(i, j int) bool {
139 if r.Reasons[keys[i]] != r.Reasons[keys[j]] {
140 return r.Reasons[keys[i]] > r.Reasons[keys[j]]
141 }
142 return keys[i] < keys[j]
143 })
144 for _, k := range keys {
145 fmt.Fprintf(&b, " %5d %s\n", r.Reasons[k], k)
146 }
147 fmt.Fprintf(&b, "anomalies: %d\n", len(r.Anomalies))
148 for _, a := range r.Anomalies {
149 fmt.Fprintf(&b, " ! %s\n", a)
150 }
151 return b.String()
152 }
153
View as plain text