|
60 | 60 | ) |
61 | 61 | ) |
62 | 62 |
|
| 63 | +;; Same as the above but with call_indirect |
| 64 | +(module |
| 65 | + ;; CHECK: (type $nopType (func (param i32))) |
| 66 | + (type $nopType (func (param i32))) |
| 67 | + |
| 68 | + (table 1 1 funcref) |
| 69 | + |
| 70 | + ;; CHECK: (func $nop (type $nopType) (param $0 i32) |
| 71 | + ;; CHECK-NEXT: (nop) |
| 72 | + ;; CHECK-NEXT: ) |
| 73 | + (func $nop (export "nop") (type $nopType) |
| 74 | + (nop) |
| 75 | + ) |
| 76 | + |
| 77 | + ;; CHECK: (func $calls-nop-via-ref (type $1) |
| 78 | + ;; CHECK-NEXT: (call_indirect $0 (type $nopType) |
| 79 | + ;; CHECK-NEXT: (i32.const 1) |
| 80 | + ;; CHECK-NEXT: (i32.const 0) |
| 81 | + ;; CHECK-NEXT: ) |
| 82 | + ;; CHECK-NEXT: ) |
| 83 | + (func $calls-nop-via-ref |
| 84 | + ;; This can only possibly be a nop in closed-world. |
| 85 | + ;; Ideally vacuum could optimize this out but we don't have a way to share |
| 86 | + ;; this information with other passes today. |
| 87 | + ;; For now, we can at least annotate that the call to this function in $f |
| 88 | + ;; has no effects. |
| 89 | + ;; TODO: This call_ref could be marked as having no effects, like the call below. |
| 90 | + (call_indirect (type $nopType) (i32.const 1) (i32.const 0)) |
| 91 | + ) |
| 92 | + |
| 93 | + ;; CHECK: (func $f (type $1) |
| 94 | + ;; CHECK-NEXT: (nop) |
| 95 | + ;; CHECK-NEXT: ) |
| 96 | + (func $f |
| 97 | + ;; $calls-nop-via-ref has no effects because we determined that it can only |
| 98 | + ;; call $nop. We can optimize this call out. |
| 99 | + (call $calls-nop-via-ref) |
| 100 | + ) |
| 101 | +) |
| 102 | + |
63 | 103 | (module |
64 | 104 | ;; CHECK: (type $maybe-has-effects (func (param i32))) |
65 | 105 | (type $maybe-has-effects (func (param i32))) |
|
100 | 140 | ) |
101 | 141 | ) |
102 | 142 |
|
| 143 | +;; Same as above but with call_indirect |
| 144 | +(module |
| 145 | + (table 1 1 funcref) |
| 146 | + |
| 147 | + ;; CHECK: (type $maybe-has-effects (func (param i32))) |
| 148 | + (type $maybe-has-effects (func (param i32))) |
| 149 | + |
| 150 | + ;; CHECK: (func $unreachable (type $maybe-has-effects) (param $0 i32) |
| 151 | + ;; CHECK-NEXT: (unreachable) |
| 152 | + ;; CHECK-NEXT: ) |
| 153 | + (func $unreachable (export "unreachable") (type $maybe-has-effects) (param i32) |
| 154 | + (unreachable) |
| 155 | + ) |
| 156 | + |
| 157 | + ;; CHECK: (func $nop2 (type $maybe-has-effects) (param $0 i32) |
| 158 | + ;; CHECK-NEXT: (nop) |
| 159 | + ;; CHECK-NEXT: ) |
| 160 | + (func $nop2 (export "nop2") (type $maybe-has-effects) (param i32) |
| 161 | + (nop) |
| 162 | + ) |
| 163 | + |
| 164 | + ;; CHECK: (func $calls-effectful-function-via-ref (type $1) |
| 165 | + ;; CHECK-NEXT: (call_indirect $0 (type $maybe-has-effects) |
| 166 | + ;; CHECK-NEXT: (i32.const 1) |
| 167 | + ;; CHECK-NEXT: (i32.const 1) |
| 168 | + ;; CHECK-NEXT: ) |
| 169 | + ;; CHECK-NEXT: ) |
| 170 | + (func $calls-effectful-function-via-ref |
| 171 | + (call_indirect (type $maybe-has-effects) (i32.const 1) (i32.const 1)) |
| 172 | + ) |
| 173 | + |
| 174 | + ;; CHECK: (func $f (type $1) |
| 175 | + ;; CHECK-NEXT: (call $calls-effectful-function-via-ref) |
| 176 | + ;; CHECK-NEXT: ) |
| 177 | + (func $f |
| 178 | + ;; This may be a nop or it may trap depending on the ref. |
| 179 | + ;; We don't know so don't optimize it out. |
| 180 | + (call $calls-effectful-function-via-ref) |
| 181 | + ) |
| 182 | +) |
| 183 | + |
103 | 184 | (module |
104 | 185 | ;; CHECK: (type $uninhabited (func (param i32))) |
105 | 186 | (type $uninhabited (func (param i32))) |
|
150 | 231 | ) |
151 | 232 |
|
152 | 233 | (module |
153 | | - ;; CHECK: (type $super (sub (struct))) |
154 | | - (type $super (sub (struct))) |
155 | | - ;; CHECK: (type $sub (sub $super (struct))) |
156 | | - (type $sub (sub $super (struct))) |
157 | | - |
158 | | - ;; Supertype |
159 | | - ;; CHECK: (type $func-with-sub-param (sub (func (param (ref $sub))))) |
160 | | - (type $func-with-sub-param (sub (func (param (ref $sub))))) |
| 234 | + ;; CHECK: (type $super (sub (func))) |
| 235 | + (type $super (sub (func))) |
161 | 236 | ;; Subtype |
162 | | - ;; CHECK: (type $func-with-super-param (sub $func-with-sub-param (func (param (ref $super))))) |
163 | | - (type $func-with-super-param (sub $func-with-sub-param (func (param (ref $super))))) |
| 237 | + ;; CHECK: (type $sub (sub $super (func))) |
| 238 | + (type $sub (sub $super (func))) |
164 | 239 |
|
165 | | - ;; CHECK: (func $nop-with-supertype (type $func-with-sub-param) (param $0 (ref $sub)) |
| 240 | + ;; CHECK: (func $nop-with-supertype (type $super) |
166 | 241 | ;; CHECK-NEXT: (nop) |
167 | 242 | ;; CHECK-NEXT: ) |
168 | | - (func $nop-with-supertype (export "nop-with-supertype") (type $func-with-sub-param) (param (ref $sub)) |
| 243 | + (func $nop-with-supertype (export "nop-with-supertype") (type $super) |
169 | 244 | ) |
170 | 245 |
|
171 | | - ;; CHECK: (func $effectful-with-subtype (type $func-with-super-param) (param $0 (ref $super)) |
| 246 | + ;; CHECK: (func $effectful-with-subtype (type $sub) |
172 | 247 | ;; CHECK-NEXT: (unreachable) |
173 | 248 | ;; CHECK-NEXT: ) |
174 | | - (func $effectful-with-subtype (export "effectful-with-subtype") (type $func-with-super-param) (param (ref $super)) |
| 249 | + (func $effectful-with-subtype (export "effectful-with-subtype") (type $sub) |
175 | 250 | (unreachable) |
176 | 251 | ) |
177 | 252 |
|
178 | | - ;; CHECK: (func $calls-ref-with-subtype (type $3) (param $func (ref $func-with-sub-param)) (param $sub (ref $sub)) |
179 | | - ;; CHECK-NEXT: (call_ref $func-with-sub-param |
180 | | - ;; CHECK-NEXT: (local.get $sub) |
| 253 | + ;; CHECK: (func $calls-ref-with-supertype (type $1) (param $func (ref $super)) |
| 254 | + ;; CHECK-NEXT: (call_ref $super |
181 | 255 | ;; CHECK-NEXT: (local.get $func) |
182 | 256 | ;; CHECK-NEXT: ) |
183 | 257 | ;; CHECK-NEXT: ) |
184 | | - (func $calls-ref-with-subtype (param $func (ref $func-with-sub-param)) (param $sub (ref $sub)) |
185 | | - (call_ref $func-with-sub-param (local.get $sub) (local.get $func)) |
| 258 | + (func $calls-ref-with-supertype (param $func (ref $super)) |
| 259 | + (call_ref $super (local.get $func)) |
186 | 260 | ) |
187 | 261 |
|
188 | | - ;; CHECK: (func $f (type $3) (param $func (ref $func-with-sub-param)) (param $sub (ref $sub)) |
189 | | - ;; CHECK-NEXT: (call $calls-ref-with-subtype |
| 262 | + ;; CHECK: (func $f (type $1) (param $func (ref $super)) |
| 263 | + ;; CHECK-NEXT: (call $calls-ref-with-supertype |
190 | 264 | ;; CHECK-NEXT: (local.get $func) |
191 | | - ;; CHECK-NEXT: (local.get $sub) |
192 | 265 | ;; CHECK-NEXT: ) |
193 | 266 | ;; CHECK-NEXT: ) |
194 | | - (func $f (param $func (ref $func-with-sub-param)) (param $sub (ref $sub)) |
| 267 | + (func $f (param $func (ref $super)) |
195 | 268 | ;; Check that we account for subtyping correctly. |
196 | | - ;; The type $func-with-sub-param (the supertype) has no effects (i.e. the |
197 | | - ;; union of all effects of functions with this type is empty). |
198 | | - ;; However, a subtype of $func-with-sub-param ($func-with-super-param) does |
199 | | - ;; have effects, and we can call_ref with that subtype, so we need to |
200 | | - ;; include the unreachable effect and we can't optimize out this call. |
201 | | - (call $calls-ref-with-subtype (local.get $func) (local.get $sub)) |
| 269 | + ;; $super has no effects (i.e. the union of all effects of functions with |
| 270 | + ;; this type is empty). However, $sub does have effects, and we can call_ref |
| 271 | + ;; with that subtype, so we need to include the unreachable effect and we |
| 272 | + ;; can't optimize out this call. |
| 273 | + (call $calls-ref-with-supertype (local.get $func)) |
202 | 274 | ) |
203 | 275 | ) |
204 | 276 |
|
205 | 277 | ;; Same as above but this time our reference is the exact supertype |
206 | 278 | ;; so we know not to aggregate effects from the subtype. |
207 | 279 | ;; TODO: this case doesn't optimize today. Add exact ref support in the pass. |
208 | 280 | (module |
209 | | - ;; CHECK: (type $super (sub (struct))) |
210 | | - (type $super (sub (struct))) |
211 | | - ;; CHECK: (type $sub (sub $super (struct))) |
212 | | - (type $sub (sub $super (struct))) |
213 | | - |
214 | | - ;; Supertype |
215 | | - ;; CHECK: (type $func-with-sub-param (sub (func (param (ref $sub))))) |
216 | | - (type $func-with-sub-param (sub (func (param (ref $sub))))) |
217 | | - ;; Subtype |
218 | | - ;; CHECK: (type $func-with-super-param (sub $func-with-sub-param (func (param (ref $super))))) |
219 | | - (type $func-with-super-param (sub $func-with-sub-param (func (param (ref $super))))) |
| 281 | + ;; CHECK: (type $super (sub (func))) |
| 282 | + (type $super (sub (func))) |
| 283 | + |
| 284 | + ;; CHECK: (type $sub (sub $super (func))) |
| 285 | + (type $sub (sub $super (func))) |
220 | 286 |
|
221 | | - ;; CHECK: (func $nop-with-supertype (type $func-with-sub-param) (param $0 (ref $sub)) |
| 287 | + ;; CHECK: (func $nop-with-supertype (type $super) |
222 | 288 | ;; CHECK-NEXT: (nop) |
223 | 289 | ;; CHECK-NEXT: ) |
224 | | - (func $nop-with-supertype (export "nop-with-supertype") (type $func-with-sub-param) (param (ref $sub)) |
| 290 | + (func $nop-with-supertype (export "nop-with-supertype") (type $super) |
225 | 291 | ) |
226 | 292 |
|
227 | | - ;; CHECK: (func $effectful-with-subtype (type $func-with-super-param) (param $0 (ref $super)) |
| 293 | + ;; CHECK: (func $effectful-with-subtype (type $sub) |
228 | 294 | ;; CHECK-NEXT: (unreachable) |
229 | 295 | ;; CHECK-NEXT: ) |
230 | | - (func $effectful-with-subtype (export "effectful-with-subtype") (type $func-with-super-param) (param (ref $super)) |
| 296 | + (func $effectful-with-subtype (export "effectful-with-subtype") (type $sub) |
231 | 297 | (unreachable) |
232 | 298 | ) |
233 | 299 |
|
234 | | - ;; CHECK: (func $calls-ref-with-subtype (type $3) (param $func (ref (exact $func-with-sub-param))) (param $sub (ref $sub)) |
235 | | - ;; CHECK-NEXT: (call_ref $func-with-sub-param |
236 | | - ;; CHECK-NEXT: (local.get $sub) |
| 300 | + ;; CHECK: (func $calls-ref-with-supertype (type $1) (param $func (ref (exact $super))) |
| 301 | + ;; CHECK-NEXT: (call_ref $super |
237 | 302 | ;; CHECK-NEXT: (local.get $func) |
238 | 303 | ;; CHECK-NEXT: ) |
239 | 304 | ;; CHECK-NEXT: ) |
240 | | - (func $calls-ref-with-subtype (param $func (ref (exact $func-with-sub-param))) (param $sub (ref $sub)) |
241 | | - (call_ref $func-with-sub-param (local.get $sub) (local.get $func)) |
| 305 | + (func $calls-ref-with-supertype (param $func (ref (exact $super))) |
| 306 | + (call_ref $super (local.get $func)) |
242 | 307 | ) |
243 | 308 |
|
244 | | - ;; CHECK: (func $f (type $3) (param $func (ref (exact $func-with-sub-param))) (param $sub (ref $sub)) |
245 | | - ;; CHECK-NEXT: (call $calls-ref-with-subtype |
| 309 | + ;; CHECK: (func $f (type $1) (param $func (ref (exact $super))) |
| 310 | + ;; CHECK-NEXT: (call $calls-ref-with-supertype |
246 | 311 | ;; CHECK-NEXT: (local.get $func) |
247 | | - ;; CHECK-NEXT: (local.get $sub) |
248 | 312 | ;; CHECK-NEXT: ) |
249 | 313 | ;; CHECK-NEXT: ) |
250 | | - (func $f (param $func (ref (exact $func-with-sub-param))) (param $sub (ref $sub)) |
251 | | - (call $calls-ref-with-subtype (local.get $func) (local.get $sub)) |
| 314 | + (func $f (param $func (ref (exact $super))) |
| 315 | + (call $calls-ref-with-supertype (local.get $func)) |
252 | 316 | ) |
253 | 317 | ) |
254 | 318 |
|
|
0 commit comments