Skip to content

Commit bb1c44a

Browse files
authored
optimize if and select in the case their values are identical (#1013)
1 parent 443cfe9 commit bb1c44a

File tree

7 files changed

+190
-67
lines changed

7 files changed

+190
-67
lines changed

src/passes/OptimizeInstructions.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,18 @@ struct OptimizeInstructions : public WalkerPass<PostWalker<OptimizeInstructions,
596596
std::swap(iff->ifTrue, iff->ifFalse);
597597
}
598598
}
599+
if (ExpressionAnalyzer::equal(iff->ifTrue, iff->ifFalse)) {
600+
// sides are identical, fold
601+
if (!EffectAnalyzer(getPassOptions(), iff->condition).hasSideEffects()) {
602+
return iff->ifTrue;
603+
} else {
604+
Builder builder(*getModule());
605+
return builder.makeSequence(
606+
builder.makeDrop(iff->condition),
607+
iff->ifTrue
608+
);
609+
}
610+
}
599611
}
600612
} else if (auto* select = curr->dynCast<Select>()) {
601613
select->condition = optimizeBoolean(select->condition);
@@ -609,6 +621,33 @@ struct OptimizeInstructions : public WalkerPass<PostWalker<OptimizeInstructions,
609621
std::swap(select->ifTrue, select->ifFalse);
610622
}
611623
}
624+
if (ExpressionAnalyzer::equal(select->ifTrue, select->ifFalse)) {
625+
// sides are identical, fold
626+
EffectAnalyzer value(getPassOptions(), select->ifTrue);
627+
if (value.hasSideEffects()) {
628+
// at best we don't need the condition, but need to execute the value
629+
// twice. a block is larger than a select by 2 bytes, and
630+
// we must drop one value, so 3, while we save the condition,
631+
// so it's not clear this is worth it, TODO
632+
} else {
633+
// value has no side effects
634+
EffectAnalyzer condition(getPassOptions(), select->condition);
635+
if (!condition.hasSideEffects()) {
636+
return select->ifTrue;
637+
} else {
638+
// the condition is last, so we need a new local, and it may be
639+
// a bad idea to use a block like we do for an if. Do it only if we
640+
// can reorder
641+
if (!condition.invalidates(value)) {
642+
Builder builder(*getModule());
643+
return builder.makeSequence(
644+
builder.makeDrop(select->condition),
645+
select->ifTrue
646+
);
647+
}
648+
}
649+
}
650+
}
612651
} else if (auto* br = curr->dynCast<Break>()) {
613652
if (br->condition) {
614653
br->condition = optimizeBoolean(br->condition);

test/passes/O.bin.txt

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,7 @@
4343
)
4444
)
4545
(func $2 (type $0) (param $0 i64) (result i64)
46-
(if
47-
(i64.eq
48-
(get_local $0)
49-
(i64.const 0)
50-
)
51-
(unreachable)
52-
(unreachable)
53-
)
46+
(unreachable)
5447
)
5548
(func $3 (type $0) (param $0 i64) (result i64)
5649
(local $1 i64)

test/passes/optimize-instructions.txt

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@
406406
(if i32
407407
(i32.const 1)
408408
(call $ne0)
409-
(call $ne0)
409+
(call $ne1)
410410
)
411411
(nop)
412412
)
@@ -418,6 +418,9 @@
418418
(nop)
419419
)
420420
)
421+
(func $ne1 (type $2) (result i32)
422+
(unreachable)
423+
)
421424
(func $load-off-2 (type $3) (param $0 i32) (result i32)
422425
(i32.store
423426
(i32.const 6)
@@ -1882,4 +1885,81 @@
18821885
)
18831886
)
18841887
)
1888+
(func $if-parallel (type $4) (param $0 i32) (param $1 i32)
1889+
(drop
1890+
(i32.add
1891+
(get_local $1)
1892+
(i32.const 1)
1893+
)
1894+
)
1895+
(drop
1896+
(block i32
1897+
(drop
1898+
(tee_local $0
1899+
(get_local $1)
1900+
)
1901+
)
1902+
(i32.add
1903+
(get_local $1)
1904+
(i32.const 1)
1905+
)
1906+
)
1907+
)
1908+
)
1909+
(func $select-parallel (type $4) (param $0 i32) (param $1 i32)
1910+
(drop
1911+
(i32.add
1912+
(get_local $1)
1913+
(i32.const 1)
1914+
)
1915+
)
1916+
(drop
1917+
(select
1918+
(tee_local $0
1919+
(get_local $1)
1920+
)
1921+
(tee_local $0
1922+
(get_local $1)
1923+
)
1924+
(get_local $0)
1925+
)
1926+
)
1927+
(drop
1928+
(block i32
1929+
(drop
1930+
(tee_local $0
1931+
(get_local $1)
1932+
)
1933+
)
1934+
(i32.add
1935+
(get_local $1)
1936+
(i32.const 1)
1937+
)
1938+
)
1939+
)
1940+
(drop
1941+
(select
1942+
(tee_local $0
1943+
(get_local $1)
1944+
)
1945+
(tee_local $0
1946+
(get_local $1)
1947+
)
1948+
(tee_local $0
1949+
(get_local $1)
1950+
)
1951+
)
1952+
)
1953+
(drop
1954+
(select
1955+
(tee_local $0
1956+
(get_local $1)
1957+
)
1958+
(tee_local $0
1959+
(get_local $1)
1960+
)
1961+
(unreachable)
1962+
)
1963+
)
1964+
)
18851965
)

test/passes/optimize-instructions.wast

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@
319319
(if i32
320320
(i32.const 1)
321321
(i32.ne (call $ne0) (i32.const 0))
322-
(i32.ne (call $ne0) (i32.const 0))
322+
(i32.ne (call $ne1) (i32.const 0))
323323
)
324324
(nop)
325325
)
@@ -331,6 +331,9 @@
331331
(nop)
332332
)
333333
)
334+
(func $ne1 (result i32)
335+
(unreachable)
336+
)
334337
(func $load-off-2 "load-off-2" (param $0 i32) (result i32)
335338
(i32.store offset=2
336339
(i32.add
@@ -2303,4 +2306,57 @@
23032306
)
23042307
)
23052308
)
2309+
(func $if-parallel (param $0 i32) (param $1 i32)
2310+
(drop
2311+
(if i32
2312+
(get_local $0)
2313+
(i32.add (get_local $1) (i32.const 1))
2314+
(i32.add (get_local $1) (i32.const 1))
2315+
)
2316+
)
2317+
(drop
2318+
(if i32
2319+
(tee_local $0 (get_local $1)) ;; side effects!
2320+
(i32.add (get_local $1) (i32.const 1))
2321+
(i32.add (get_local $1) (i32.const 1))
2322+
)
2323+
)
2324+
)
2325+
(func $select-parallel (param $0 i32) (param $1 i32)
2326+
(drop
2327+
(select
2328+
(i32.add (get_local $1) (i32.const 1))
2329+
(i32.add (get_local $1) (i32.const 1))
2330+
(get_local $0)
2331+
)
2332+
)
2333+
(drop
2334+
(select
2335+
(tee_local $0 (get_local $1)) ;; side effects!
2336+
(tee_local $0 (get_local $1)) ;; side effects!
2337+
(get_local $0)
2338+
)
2339+
)
2340+
(drop
2341+
(select
2342+
(i32.add (get_local $1) (i32.const 1))
2343+
(i32.add (get_local $1) (i32.const 1))
2344+
(tee_local $0 (get_local $1)) ;; side effects! (but no interference with values)
2345+
)
2346+
)
2347+
(drop
2348+
(select
2349+
(tee_local $0 (get_local $1)) ;; side effects! interference!
2350+
(tee_local $0 (get_local $1)) ;; side effects! interference!
2351+
(tee_local $0 (get_local $1)) ;; side effects! interference!
2352+
)
2353+
)
2354+
(drop
2355+
(select
2356+
(tee_local $0 (get_local $1)) ;; side effects!
2357+
(tee_local $0 (get_local $1)) ;; side effects!
2358+
(unreachable) ;; side effects! (but no interference with values)
2359+
)
2360+
)
2361+
)
23062362
)

test/wasm-only.fromasm

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -306,29 +306,14 @@
306306
(i64.const 0)
307307
)
308308
(func $ifValue64 (param $0 i64) (param $1 i64) (result i64)
309-
(if i64
310-
(i32.wrap/i64
311-
(get_local $1)
312-
)
313-
(call $call2
314-
(get_local $0)
315-
)
316-
(call $call2
317-
(get_local $0)
318-
)
309+
(call $call2
310+
(get_local $0)
319311
)
320312
)
321313
(func $ifValue32 (param $0 i32) (param $1 i32) (result i32)
322-
(if i32
314+
(call $ifValue32
315+
(get_local $0)
323316
(get_local $1)
324-
(call $ifValue32
325-
(get_local $0)
326-
(get_local $1)
327-
)
328-
(call $ifValue32
329-
(get_local $0)
330-
(get_local $1)
331-
)
332317
)
333318
)
334319
(func $switch64 (param $0 i64) (result i32)

test/wasm-only.fromasm.clamp

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -306,29 +306,14 @@
306306
(i64.const 0)
307307
)
308308
(func $ifValue64 (param $0 i64) (param $1 i64) (result i64)
309-
(if i64
310-
(i32.wrap/i64
311-
(get_local $1)
312-
)
313-
(call $call2
314-
(get_local $0)
315-
)
316-
(call $call2
317-
(get_local $0)
318-
)
309+
(call $call2
310+
(get_local $0)
319311
)
320312
)
321313
(func $ifValue32 (param $0 i32) (param $1 i32) (result i32)
322-
(if i32
314+
(call $ifValue32
315+
(get_local $0)
323316
(get_local $1)
324-
(call $ifValue32
325-
(get_local $0)
326-
(get_local $1)
327-
)
328-
(call $ifValue32
329-
(get_local $0)
330-
(get_local $1)
331-
)
332317
)
333318
)
334319
(func $switch64 (param $0 i64) (result i32)

test/wasm-only.fromasm.imprecise

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -221,29 +221,14 @@
221221
(i64.const 0)
222222
)
223223
(func $ifValue64 (param $0 i64) (param $1 i64) (result i64)
224-
(if i64
225-
(i32.wrap/i64
226-
(get_local $1)
227-
)
228-
(call $call2
229-
(get_local $0)
230-
)
231-
(call $call2
232-
(get_local $0)
233-
)
224+
(call $call2
225+
(get_local $0)
234226
)
235227
)
236228
(func $ifValue32 (param $0 i32) (param $1 i32) (result i32)
237-
(if i32
229+
(call $ifValue32
230+
(get_local $0)
238231
(get_local $1)
239-
(call $ifValue32
240-
(get_local $0)
241-
(get_local $1)
242-
)
243-
(call $ifValue32
244-
(get_local $0)
245-
(get_local $1)
246-
)
247232
)
248233
)
249234
(func $switch64 (param $0 i64) (result i32)

0 commit comments

Comments
 (0)