File tree Expand file tree Collapse file tree 3 files changed +59
-9
lines changed Expand file tree Collapse file tree 3 files changed +59
-9
lines changed Original file line number Diff line number Diff line change @@ -422,6 +422,15 @@ struct Checker
422
422
// away repeated apperances if it has any.
423
423
EffectAnalyzer effects (options, getModule ()->features , curr);
424
424
425
+ // We can ignore traps here, as we replace a repeating expression with a
426
+ // single appearance of it, a store to a local, and gets in the other
427
+ // locations, and so if the expression traps then the first appearance -
428
+ // that we keep around - would trap, and the others are never reached
429
+ // anyhow. (The other checks we perform here, including invalidation and
430
+ // determinism, will ensure that either all of the appearances trap, or
431
+ // none of them.)
432
+ effects.trap = false ;
433
+
425
434
// We also cannot optimize away something that is intrinsically
426
435
// nondeterministic: even if it has no side effects, if it may return a
427
436
// different result each time, then we cannot optimize away repeats.
Original file line number Diff line number Diff line change 266
266
)
267
267
268
268
;; CHECK: (func $loads
269
+ ;; CHECK-NEXT: (local $0 i32)
269
270
;; CHECK-NEXT: (drop
270
- ;; CHECK-NEXT: (i32.load
271
- ;; CHECK-NEXT: (i32.const 10)
271
+ ;; CHECK-NEXT: (local.tee $0
272
+ ;; CHECK-NEXT: (i32.load
273
+ ;; CHECK-NEXT: (i32.const 10)
274
+ ;; CHECK-NEXT: )
272
275
;; CHECK-NEXT: )
273
276
;; CHECK-NEXT: )
274
277
;; CHECK-NEXT: (drop
275
- ;; CHECK-NEXT: (i32.load
276
- ;; CHECK-NEXT: (i32.const 10)
277
- ;; CHECK-NEXT: )
278
+ ;; CHECK-NEXT: (local.get $0)
278
279
;; CHECK-NEXT: )
279
280
;; CHECK-NEXT: )
280
281
(func $loads
281
- ;; The possible trap on loads prevents optimization.
282
- ;; TODO: optimize that too
282
+ ;; The possible trap on loads does not prevent optimization, since if we
283
+ ;; trap then it doesn't matter that we replaced the later expression.
283
284
(drop
284
285
(i32.load (i32.const 10 ))
285
286
)
Original file line number Diff line number Diff line change 65
65
;; CHECK: (type $B (array (mut i32)))
66
66
(type $B (array (mut i32 )))
67
67
68
+
69
+ ;; CHECK: (type $ref?|$A|_=>_none (func (param (ref null $A))))
70
+
68
71
;; CHECK: (type $none_=>_none (func))
69
72
73
+ ;; CHECK: (func $struct-gets-nullable (param $ref (ref null $A))
74
+ ;; CHECK-NEXT: (local $1 i32)
75
+ ;; CHECK-NEXT: (drop
76
+ ;; CHECK-NEXT: (local.tee $1
77
+ ;; CHECK-NEXT: (struct.get $A 0
78
+ ;; CHECK-NEXT: (local.get $ref)
79
+ ;; CHECK-NEXT: )
80
+ ;; CHECK-NEXT: )
81
+ ;; CHECK-NEXT: )
82
+ ;; CHECK-NEXT: (drop
83
+ ;; CHECK-NEXT: (local.get $1)
84
+ ;; CHECK-NEXT: )
85
+ ;; CHECK-NEXT: (drop
86
+ ;; CHECK-NEXT: (local.get $1)
87
+ ;; CHECK-NEXT: )
88
+ ;; CHECK-NEXT: )
89
+ (func $struct-gets-nullable (param $ref (ref null $A ))
90
+ ;; Repeated loads from a struct can be optimized, even with a nullable
91
+ ;; reference: if we trap, it does not matter that we replaced the later
92
+ ;; expressions).
93
+ (drop
94
+ (struct.get $A 0
95
+ (local.get $ref )
96
+ )
97
+ )
98
+ (drop
99
+ (struct.get $A 0
100
+ (local.get $ref )
101
+ )
102
+ )
103
+ (drop
104
+ (struct.get $A 0
105
+ (local.get $ref )
106
+ )
107
+ )
108
+ )
109
+
70
110
;; CHECK: (func $struct-gets (param $ref (ref $A))
71
111
;; CHECK-NEXT: (local $1 i32)
72
112
;; CHECK-NEXT: (drop
86
126
(func $struct-gets (param $ref (ref $A ))
87
127
;; Repeated loads from a struct can be optimized.
88
128
;;
89
- ;; Note that these struct.gets cannot trap as the reference is non-nullable,
90
- ;; so there are no side effects here , and we can optimize.
129
+ ;; A potential trap would not stop us (see previous testcase), but here
130
+ ;; there is also no trap possible anyhow , and we should optimize.
91
131
(drop
92
132
(struct.get $A 0
93
133
(local.get $ref )
You can’t perform that action at this time.
0 commit comments