blob: 1514686504f778d3c7fe0bba60a711dfd086b649 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
|
/*
* Copyright 2016 WebAssembly Community Group participants
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef wasm_ast_cost_h
#define wasm_ast_cost_h
namespace wasm {
// Measure the execution cost of an AST. Very handwave-ey
struct CostAnalyzer : public Visitor<CostAnalyzer, Index> {
CostAnalyzer(Expression *ast) {
assert(ast);
cost = visit(ast);
}
Index cost;
Index maybeVisit(Expression* curr) {
return curr ? visit(curr) : 0;
}
Index visitBlock(Block *curr) {
Index ret = 0;
for (auto* child : curr->list) ret += visit(child);
return ret;
}
Index visitIf(If *curr) {
return 1 + visit(curr->condition) + std::max(visit(curr->ifTrue), maybeVisit(curr->ifFalse));
}
Index visitLoop(Loop *curr) {
return 5 * visit(curr->body);
}
Index visitBreak(Break *curr) {
return 1 + maybeVisit(curr->value) + maybeVisit(curr->condition);
}
Index visitSwitch(Switch *curr) {
return 2 + visit(curr->condition) + maybeVisit(curr->value);
}
Index visitCall(Call *curr) {
Index ret = 4;
for (auto* child : curr->operands) ret += visit(child);
return ret;
}
Index visitCallImport(CallImport *curr) {
Index ret = 15;
for (auto* child : curr->operands) ret += visit(child);
return ret;
}
Index visitCallIndirect(CallIndirect *curr) {
Index ret = 6 + visit(curr->target);
for (auto* child : curr->operands) ret += visit(child);
return ret;
}
Index visitGetLocal(GetLocal *curr) {
return 0;
}
Index visitSetLocal(SetLocal *curr) {
return 1;
}
Index visitGetGlobal(GetGlobal *curr) {
return 1;
}
Index visitSetGlobal(SetGlobal *curr) {
return 2;
}
Index visitLoad(Load *curr) {
return 1 + visit(curr->ptr);
}
Index visitStore(Store *curr) {
return 2 + visit(curr->ptr) + visit(curr->value);
}
Index visitConst(Const *curr) {
return 1;
}
Index visitUnary(Unary *curr) {
Index ret = 0;
switch (curr->op) {
case ClzInt32:
case CtzInt32:
case PopcntInt32:
case NegFloat32:
case AbsFloat32:
case CeilFloat32:
case FloorFloat32:
case TruncFloat32:
case NearestFloat32:
case ClzInt64:
case CtzInt64:
case PopcntInt64:
case NegFloat64:
case AbsFloat64:
case CeilFloat64:
case FloorFloat64:
case TruncFloat64:
case NearestFloat64:
case EqZInt32:
case EqZInt64:
case ExtendSInt32:
case ExtendUInt32:
case WrapInt64:
case PromoteFloat32:
case DemoteFloat64:
case TruncSFloat32ToInt32:
case TruncUFloat32ToInt32:
case TruncSFloat64ToInt32:
case TruncUFloat64ToInt32:
case ReinterpretFloat32:
case TruncSFloat32ToInt64:
case TruncUFloat32ToInt64:
case TruncSFloat64ToInt64:
case TruncUFloat64ToInt64:
case ReinterpretFloat64:
case ReinterpretInt32:
case ConvertSInt32ToFloat32:
case ConvertUInt32ToFloat32:
case ConvertSInt64ToFloat32:
case ConvertUInt64ToFloat32:
case ReinterpretInt64:
case ConvertSInt32ToFloat64:
case ConvertUInt32ToFloat64:
case ConvertSInt64ToFloat64:
case ConvertUInt64ToFloat64: ret = 1; break;
case SqrtFloat32:
case SqrtFloat64: ret = 2; break;
default: WASM_UNREACHABLE();
}
return ret + visit(curr->value);
}
Index visitBinary(Binary *curr) {
Index ret = 0;
switch (curr->op) {
case AddInt32: ret = 1; break;
case SubInt32: ret = 1; break;
case MulInt32: ret = 2; break;
case DivSInt32: ret = 3; break;
case DivUInt32: ret = 3; break;
case RemSInt32: ret = 3; break;
case RemUInt32: ret = 3; break;
case AndInt32: ret = 1; break;
case OrInt32: ret = 1; break;
case XorInt32: ret = 1; break;
case ShlInt32: ret = 1; break;
case ShrUInt32: ret = 1; break;
case ShrSInt32: ret = 1; break;
case RotLInt32: ret = 1; break;
case RotRInt32: ret = 1; break;
case AddInt64: ret = 1; break;
case SubInt64: ret = 1; break;
case MulInt64: ret = 2; break;
case DivSInt64: ret = 3; break;
case DivUInt64: ret = 3; break;
case RemSInt64: ret = 3; break;
case RemUInt64: ret = 3; break;
case AndInt64: ret = 1; break;
case OrInt64: ret = 1; break;
case XorInt64: ret = 1; break;
case ShlInt64: ret = 1; break;
case ShrUInt64: ret = 1; break;
case ShrSInt64: ret = 1; break;
case RotLInt64: ret = 1; break;
case RotRInt64: ret = 1; break;
case AddFloat32: ret = 1; break;
case SubFloat32: ret = 1; break;
case MulFloat32: ret = 2; break;
case DivFloat32: ret = 3; break;
case CopySignFloat32: ret = 1; break;
case MinFloat32: ret = 1; break;
case MaxFloat32: ret = 1; break;
case AddFloat64: ret = 1; break;
case SubFloat64: ret = 1; break;
case MulFloat64: ret = 2; break;
case DivFloat64: ret = 3; break;
case CopySignFloat64: ret = 1; break;
case MinFloat64: ret = 1; break;
case MaxFloat64: ret = 1; break;
case LtUInt32: ret = 1; break;
case LtSInt32: ret = 1; break;
case LeUInt32: ret = 1; break;
case LeSInt32: ret = 1; break;
case GtUInt32: ret = 1; break;
case GtSInt32: ret = 1; break;
case GeUInt32: ret = 1; break;
case GeSInt32: ret = 1; break;
case LtUInt64: ret = 1; break;
case LtSInt64: ret = 1; break;
case LeUInt64: ret = 1; break;
case LeSInt64: ret = 1; break;
case GtUInt64: ret = 1; break;
case GtSInt64: ret = 1; break;
case GeUInt64: ret = 1; break;
case GeSInt64: ret = 1; break;
case LtFloat32: ret = 1; break;
case GtFloat32: ret = 1; break;
case LeFloat32: ret = 1; break;
case GeFloat32: ret = 1; break;
case LtFloat64: ret = 1; break;
case GtFloat64: ret = 1; break;
case LeFloat64: ret = 1; break;
case GeFloat64: ret = 1; break;
case EqInt32: ret = 1; break;
case NeInt32: ret = 1; break;
case EqInt64: ret = 1; break;
case NeInt64: ret = 1; break;
case EqFloat32: ret = 1; break;
case NeFloat32: ret = 1; break;
case EqFloat64: ret = 1; break;
case NeFloat64: ret = 1; break;
default: WASM_UNREACHABLE();
}
return ret + visit(curr->left) + visit(curr->right);
}
Index visitSelect(Select *curr) {
return 2 + visit(curr->condition) + visit(curr->ifTrue) + visit(curr->ifFalse);
}
Index visitDrop(Drop *curr) {
return visit(curr->value);
}
Index visitReturn(Return *curr) {
return maybeVisit(curr->value);
}
Index visitHost(Host *curr) {
return 100;
}
Index visitNop(Nop *curr) {
return 0;
}
Index visitUnreachable(Unreachable *curr) {
return 0;
}
};
} // namespace wasm
#endif // wasm_ast_cost_h
|