Skip to content

Commit e5e7728

Browse files
authored
Don't reorder an implicit trap with a global side effect (#1133)
1 parent 229764b commit e5e7728

File tree

3 files changed

+77
-6
lines changed

3 files changed

+77
-6
lines changed

src/ast/effects.h

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,18 +48,18 @@ struct EffectAnalyzer : public PostWalker<EffectAnalyzer> {
4848
bool readsMemory = false;
4949
bool writesMemory = false;
5050
bool implicitTrap = false; // a load or div/rem, which may trap. we ignore trap
51-
// differences, so it is ok to reorder these, and we
52-
// also allow reordering them with other effects
53-
// (so a trap may occur later or earlier, if it is
54-
// going to occur anyhow), but we can't remove them,
55-
// they count as side effects
51+
// differences, so it is ok to reorder these, but we can't
52+
// remove them, as they count as side effects, and we
53+
// can't move them in a way that would cause other noticeable
54+
// (global) side effects
5655
bool isAtomic = false; // An atomic load/store/RMW/Cmpxchg or an operator that
5756
// has a defined ordering wrt atomics (e.g. grow_memory)
5857

5958
bool accessesLocal() { return localsRead.size() + localsWritten.size() > 0; }
6059
bool accessesGlobal() { return globalsRead.size() + globalsWritten.size() > 0; }
6160
bool accessesMemory() { return calls || readsMemory || writesMemory; }
62-
bool hasSideEffects() { return calls || localsWritten.size() > 0 || writesMemory || branches || globalsWritten.size() > 0 || implicitTrap || isAtomic; }
61+
bool hasGlobalSideEffects() { return calls || globalsWritten.size() > 0 || writesMemory || isAtomic; }
62+
bool hasSideEffects() { return hasGlobalSideEffects() || localsWritten.size() > 0 || branches || implicitTrap; }
6363
bool hasAnything() { return branches || calls || accessesLocal() || readsMemory || writesMemory || accessesGlobal() || implicitTrap || isAtomic; }
6464

6565
// checks if these effects would invalidate another set (e.g., if we write, we invalidate someone that reads, they can't be moved past us)
@@ -98,6 +98,10 @@ struct EffectAnalyzer : public PostWalker<EffectAnalyzer> {
9898
if ((implicitTrap && other.branches) || (other.implicitTrap && branches)) {
9999
return true;
100100
}
101+
// we can't reorder an implicit trap in a way that alters global state
102+
if ((implicitTrap && other.hasGlobalSideEffects()) || (other.implicitTrap && hasGlobalSideEffects())) {
103+
return true;
104+
}
101105
return false;
102106
}
103107

test/passes/simplify-locals-nostructure.txt

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,38 @@
6666
(local $x i32)
6767
(unreachable)
6868
)
69+
(func $implicit-trap-and-global-effects (type $0)
70+
(local $var$0 i32)
71+
(set_local $var$0
72+
(i32.trunc_u/f64
73+
(f64.const -nan:0xfffffffffffc3)
74+
)
75+
)
76+
(f32.store align=1
77+
(i32.const 22)
78+
(f32.const 154)
79+
)
80+
(drop
81+
(get_local $var$0)
82+
)
83+
)
84+
(func $implicit-trap-and-local-effects (type $0)
85+
(local $var$0 i32)
86+
(local $other i32)
87+
(nop)
88+
(set_local $other
89+
(i32.const 100)
90+
)
91+
(drop
92+
(i32.trunc_u/f64
93+
(f64.const -nan:0xfffffffffffc3)
94+
)
95+
)
96+
(if
97+
(i32.const 1)
98+
(drop
99+
(get_local $other)
100+
)
101+
)
102+
)
69103
)

test/passes/simplify-locals-nostructure.wast

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,38 @@
3636
)
3737
)
3838
)
39+
(func $implicit-trap-and-global-effects
40+
(local $var$0 i32)
41+
(set_local $var$0
42+
(i32.trunc_u/f64
43+
(f64.const -nan:0xfffffffffffc3) ;; this implicit trap will actually trap
44+
)
45+
)
46+
(f32.store align=1 ;; and if we move it across this store, the store will execute, having global side effects
47+
(i32.const 22)
48+
(f32.const 154)
49+
)
50+
(drop
51+
(get_local $var$0)
52+
)
53+
)
54+
(func $implicit-trap-and-local-effects
55+
(local $var$0 i32)
56+
(local $other i32)
57+
(set_local $var$0
58+
(i32.trunc_u/f64
59+
(f64.const -nan:0xfffffffffffc3) ;; this implicit trap will actually trap
60+
)
61+
)
62+
(set_local $other (i32.const 100)) ;; but it's fine to move it across a local effect, that vanishes anyhow
63+
(drop
64+
(get_local $var$0)
65+
)
66+
(if (i32.const 1)
67+
(drop
68+
(get_local $other)
69+
)
70+
)
71+
)
3972
)
4073

0 commit comments

Comments
 (0)