Skip to content

Commit 34fbbb3

Browse files
authored
determinism fix for code-folding (WebAssembly#1852)
Don't depend on the hash values for ordering - use a fixed order based on order of appearance.
1 parent 7d94900 commit 34fbbb3

4 files changed

Lines changed: 109 additions & 10 deletions

File tree

src/passes/CodeFolding.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -524,13 +524,21 @@ struct CodeFolding : public WalkerPass<ControlFlowWalker<CodeFolding>> {
524524
// if we have enough to investigate, do so
525525
if (next.size() >= 2) {
526526
// now we want to find a mergeable item - any item that is equal among a subset
527-
std::map<uint32_t, std::vector<Expression*>> hashed; // hash value => expressions with that hash
527+
std::map<Expression*, HashType> hashes; // expression => hash value
528+
std::map<HashType, std::vector<Expression*>> hashed; // hash value => expressions with that hash
528529
for (auto& tail : next) {
529530
auto* item = getItem(tail, num);
530-
hashed[ExpressionAnalyzer::hash(item)].push_back(item);
531+
auto hash = hashes[item] = ExpressionAnalyzer::hash(item);
532+
hashed[hash].push_back(item);
531533
}
532-
for (auto& iter : hashed) {
533-
auto& items = iter.second;
534+
// look at each hash value exactly once. we do this in a deterministic order.
535+
std::set<HashType> seen;
536+
for (auto& tail : next) {
537+
auto* item = getItem(tail, num);
538+
auto hash = hashes[item];
539+
if (seen.count(hash)) continue;
540+
seen.insert(hash);
541+
auto& items = hashed[hash];
534542
if (items.size() == 1) continue;
535543
assert(items.size() > 0);
536544
// look for an item that has another match.

test/passes/code-folding.txt

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,3 +140,45 @@
140140
)
141141
)
142142
)
143+
(module
144+
(type $0 (func))
145+
(global $global$0 (mut i32) (i32.const 10))
146+
(func $determinism (; 0 ;) (type $0)
147+
(block $folding-inner0
148+
(block
149+
(block $label$1
150+
(br_if $label$1
151+
(i32.const 1)
152+
)
153+
(br $folding-inner0)
154+
)
155+
(block $label$2
156+
(br_if $label$2
157+
(i32.const 0)
158+
)
159+
(if
160+
(get_global $global$0)
161+
(block $block
162+
(br $folding-inner0)
163+
)
164+
)
165+
(unreachable)
166+
)
167+
(if
168+
(get_global $global$0)
169+
(block $block1
170+
(br $folding-inner0)
171+
)
172+
)
173+
(unreachable)
174+
)
175+
)
176+
(set_global $global$0
177+
(i32.sub
178+
(get_global $global$0)
179+
(i32.const 1)
180+
)
181+
)
182+
(unreachable)
183+
)
184+
)

test/passes/code-folding.wast

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,4 +150,53 @@
150150
)
151151
)
152152
)
153+
(module
154+
(type $0 (func))
155+
(global $global$0 (mut i32) (i32.const 10))
156+
(func $determinism (; 0 ;) (type $0)
157+
(block $label$1
158+
(br_if $label$1
159+
(i32.const 1)
160+
)
161+
(set_global $global$0
162+
(i32.sub
163+
(get_global $global$0)
164+
(i32.const 1)
165+
)
166+
)
167+
(unreachable)
168+
)
169+
(block $label$2
170+
(br_if $label$2
171+
(i32.const 0)
172+
)
173+
(if
174+
(get_global $global$0)
175+
(block
176+
(set_global $global$0
177+
(i32.sub
178+
(get_global $global$0)
179+
(i32.const 1)
180+
)
181+
)
182+
(unreachable)
183+
)
184+
)
185+
(unreachable)
186+
)
187+
(if
188+
(get_global $global$0)
189+
(block
190+
(set_global $global$0
191+
(i32.sub
192+
(get_global $global$0)
193+
(i32.const 1)
194+
)
195+
)
196+
(unreachable)
197+
)
198+
)
199+
(unreachable)
200+
)
201+
)
153202

test/passes/remove-unused-names_code-folding.txt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,19 +1069,19 @@
10691069
(block
10701070
(if
10711071
(i32.const 1)
1072-
(br $folding-inner1)
1072+
(br $folding-inner0)
10731073
)
10741074
(if
10751075
(i32.const 1)
1076-
(br $folding-inner1)
1076+
(br $folding-inner0)
10771077
)
10781078
(if
10791079
(i32.const 1)
1080-
(br $folding-inner0)
1080+
(br $folding-inner1)
10811081
)
10821082
(if
10831083
(i32.const 1)
1084-
(br $folding-inner0)
1084+
(br $folding-inner1)
10851085
)
10861086
)
10871087
(return)
@@ -1098,7 +1098,7 @@
10981098
(nop)
10991099
(nop)
11001100
(drop
1101-
(i32.const 2)
1101+
(i32.const 1)
11021102
)
11031103
(unreachable)
11041104
)
@@ -1115,7 +1115,7 @@
11151115
(nop)
11161116
(nop)
11171117
(drop
1118-
(i32.const 1)
1118+
(i32.const 2)
11191119
)
11201120
(unreachable)
11211121
)

0 commit comments

Comments
 (0)