@@ -46,6 +46,8 @@ struct GetLocalCounter : public PostWalker<GetLocalCounter> {
4646 }
4747};
4848
49+ // Removes trivially unneeded sets: sets for whom there is no possible get, and
50+ // sets of the same value immediately.
4951struct UnneededSetRemover : public PostWalker <UnneededSetRemover> {
5052 PassOptions& passOptions;
5153
@@ -64,19 +66,42 @@ struct UnneededSetRemover : public PostWalker<UnneededSetRemover> {
6466 bool removed = false ;
6567
6668 void visitSetLocal (SetLocal *curr) {
69+ // If no possible uses, remove.
6770 if (getLocalCounter->num [curr->index ] == 0 ) {
68- auto * value = curr->value ;
69- if (curr->isTee ()) {
70- this ->replaceCurrent (value);
71- } else if (EffectAnalyzer (passOptions, curr->value ).hasSideEffects ()) {
72- Drop* drop = ExpressionManipulator::convert<SetLocal, Drop>(curr);
73- drop->value = value;
74- drop->finalize ();
75- } else {
76- ExpressionManipulator::nop (curr);
71+ remove (curr);
72+ }
73+ // If setting the same value as we already have, remove.
74+ auto * value = curr->value ;
75+ while (true ) {
76+ if (auto * set = value->dynCast <SetLocal>()) {
77+ if (set->index == curr->index ) {
78+ remove (curr);
79+ } else {
80+ // Handle tee chains.
81+ value = set->value ;
82+ continue ;
83+ }
84+ } else if (auto * get = value->dynCast <GetLocal>()) {
85+ if (get->index == curr->index ) {
86+ remove (curr);
87+ }
7788 }
78- removed = true ;
89+ break ;
90+ }
91+ }
92+
93+ void remove (SetLocal* set) {
94+ auto * value = set->value ;
95+ if (set->isTee ()) {
96+ replaceCurrent (value);
97+ } else if (EffectAnalyzer (passOptions, set->value ).hasSideEffects ()) {
98+ Drop* drop = ExpressionManipulator::convert<SetLocal, Drop>(set);
99+ drop->value = value;
100+ drop->finalize ();
101+ } else {
102+ ExpressionManipulator::nop (set);
79103 }
104+ removed = true ;
80105 }
81106};
82107
0 commit comments