Skip to content

Commit 0934d6c

Browse files
RemoveUnusedBrs: Optimize block tails where a dropped br_if's value is redundant (#7506)
If a block ends with a br_if followed by a value that is the same as the br_if's value (and has no side effects), the value of br_if and br_if itself are redundant and can be removed, if the br_if goes to that block anyhow. For example: (block $block (result i32) .. (drop (br_if $block (value) (condition) ) ) (value) ) => (block $block (result i32) .. (drop (condition) ) (value) ) Fixes: #7489
1 parent 1df8e5c commit 0934d6c

File tree

2 files changed

+185
-20
lines changed

2 files changed

+185
-20
lines changed

src/passes/RemoveUnusedBrs.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1263,6 +1263,45 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
12631263
tablify(curr);
12641264
// Pattern-patch ifs, recreating them when it makes sense.
12651265
restructureIf(curr);
1266+
1267+
// Optimize block tails where a dropped `br_if`'s value is redundant
1268+
// when the br_if targets the block itself:
1269+
//
1270+
// (block $block (result i32)
1271+
// ..
1272+
// (drop
1273+
// (br_if $block ;; <- MUST target parent $block
1274+
// (value)
1275+
// (condition)
1276+
// )
1277+
// )
1278+
// (value) ;; <- MUST be same as br_if's value
1279+
// )
1280+
// =>
1281+
// (block $block (result i32)
1282+
// ..
1283+
// (drop
1284+
// (condition)
1285+
// )
1286+
// (value)
1287+
// )
1288+
size_t size = curr->list.size();
1289+
auto* secondLast = curr->list[size - 2];
1290+
auto* last = curr->list[size - 1];
1291+
if (auto* drop = secondLast->dynCast<Drop>()) {
1292+
if (auto* br = drop->value->dynCast<Break>();
1293+
br && br->value && br->condition) {
1294+
if (br->name == curr->name) {
1295+
if (!EffectAnalyzer(passOptions, *getModule(), br->value)
1296+
.hasUnremovableSideEffects()) {
1297+
if (ExpressionAnalyzer::equal(br->value, last)) {
1298+
// All conditions met, perform the update.
1299+
drop->value = br->condition;
1300+
}
1301+
}
1302+
}
1303+
}
1304+
}
12661305
}
12671306
}
12681307

test/lit/passes/remove-unused-brs.wast

Lines changed: 146 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
(module
77
;; Regression test in which we need to calculate a proper LUB.
8-
;; CHECK: (func $selectify-fresh-lub (type $3) (param $x i32) (result anyref)
8+
;; CHECK: (func $selectify-fresh-lub (type $4) (param $x i32) (result anyref)
99
;; CHECK-NEXT: (select (result i31ref)
1010
;; CHECK-NEXT: (ref.null none)
1111
;; CHECK-NEXT: (ref.i31
@@ -30,7 +30,7 @@
3030
)
3131
)
3232

33-
;; CHECK: (func $selectify-simple (type $1) (param $0 i32) (result i32)
33+
;; CHECK: (func $selectify-simple (type $0) (param $0 i32) (result i32)
3434
;; CHECK-NEXT: (select
3535
;; CHECK-NEXT: (i32.const 1)
3636
;; CHECK-NEXT: (i32.lt_u
@@ -73,7 +73,7 @@
7373
)
7474
)
7575

76-
;; CHECK: (func $restructure-br_if (type $1) (param $x i32) (result i32)
76+
;; CHECK: (func $restructure-br_if (type $0) (param $x i32) (result i32)
7777
;; CHECK-NEXT: (if (result i32)
7878
;; CHECK-NEXT: (local.get $x)
7979
;; CHECK-NEXT: (then
@@ -104,12 +104,12 @@
104104
)
105105
)
106106

107-
;; CHECK: (func $nothing (type $0)
107+
;; CHECK: (func $nothing (type $1)
108108
;; CHECK-NEXT: )
109109
(func $nothing)
110110

111111

112-
;; CHECK: (func $restructure-br_if-condition-reorderable (type $1) (param $x i32) (result i32)
112+
;; CHECK: (func $restructure-br_if-condition-reorderable (type $0) (param $x i32) (result i32)
113113
;; CHECK-NEXT: (if (result i32)
114114
;; CHECK-NEXT: (block (result i32)
115115
;; CHECK-NEXT: (call $nothing)
@@ -146,7 +146,7 @@
146146
)
147147
)
148148

149-
;; CHECK: (func $restructure-br_if-value-effectful (type $1) (param $x i32) (result i32)
149+
;; CHECK: (func $restructure-br_if-value-effectful (type $0) (param $x i32) (result i32)
150150
;; CHECK-NEXT: (select
151151
;; CHECK-NEXT: (block (result i32)
152152
;; CHECK-NEXT: (call $nothing)
@@ -188,7 +188,7 @@
188188
)
189189
)
190190

191-
;; CHECK: (func $restructure-br_if-value-effectful-corner-case-1 (type $1) (param $x i32) (result i32)
191+
;; CHECK: (func $restructure-br_if-value-effectful-corner-case-1 (type $0) (param $x i32) (result i32)
192192
;; CHECK-NEXT: (block $x (result i32)
193193
;; CHECK-NEXT: (drop
194194
;; CHECK-NEXT: (br_if $x
@@ -226,14 +226,14 @@
226226
)
227227
)
228228

229-
;; CHECK: (func $get-i32 (type $4) (result i32)
229+
;; CHECK: (func $get-i32 (type $2) (result i32)
230230
;; CHECK-NEXT: (i32.const 400)
231231
;; CHECK-NEXT: )
232232
(func $get-i32 (result i32)
233233
(i32.const 400)
234234
)
235235

236-
;; CHECK: (func $restructure-br_if-value-effectful-corner-case-2 (type $1) (param $x i32) (result i32)
236+
;; CHECK: (func $restructure-br_if-value-effectful-corner-case-2 (type $0) (param $x i32) (result i32)
237237
;; CHECK-NEXT: (block $x (result i32)
238238
;; CHECK-NEXT: (drop
239239
;; CHECK-NEXT: (br_if $x
@@ -272,7 +272,7 @@
272272
(call $get-i32)
273273
)
274274
)
275-
;; CHECK: (func $restructure-br_if-value-effectful-corner-case-3 (type $1) (param $x i32) (result i32)
275+
;; CHECK: (func $restructure-br_if-value-effectful-corner-case-3 (type $0) (param $x i32) (result i32)
276276
;; CHECK-NEXT: (block $x (result i32)
277277
;; CHECK-NEXT: (drop
278278
;; CHECK-NEXT: (br_if $x
@@ -305,7 +305,7 @@
305305
)
306306
)
307307

308-
;; CHECK: (func $restructure-br_if-value-effectful-corner-case-4 (type $1) (param $x i32) (result i32)
308+
;; CHECK: (func $restructure-br_if-value-effectful-corner-case-4 (type $0) (param $x i32) (result i32)
309309
;; CHECK-NEXT: (block $x (result i32)
310310
;; CHECK-NEXT: (drop
311311
;; CHECK-NEXT: (br_if $x
@@ -340,9 +340,135 @@
340340
)
341341
)
342342

343-
;; CHECK: (func $restructure-select-no-multivalue (type $0)
343+
;; CHECK: (func $restructure-br_if-value-redundant-in-block-tail-1 (type $2) (result i32)
344+
;; CHECK-NEXT: (block $parent (result i32)
345+
;; CHECK-NEXT: (call $nothing)
346+
;; CHECK-NEXT: (drop
347+
;; CHECK-NEXT: (call $get-i32)
348+
;; CHECK-NEXT: )
349+
;; CHECK-NEXT: (i32.const 1)
350+
;; CHECK-NEXT: )
351+
;; CHECK-NEXT: )
352+
(func $restructure-br_if-value-redundant-in-block-tail-1 (result i32)
353+
;; The br_if's value is equal to the value right after it, so we can remove it.
354+
(block $parent (result i32)
355+
(call $nothing)
356+
(drop
357+
(br_if $parent
358+
(i32.const 1)
359+
(call $get-i32)
360+
)
361+
)
362+
(i32.const 1)
363+
)
364+
)
365+
366+
;; CHECK: (func $restructure-br_if-value-redundant-in-block-tail-2 (type $2) (result i32)
367+
;; CHECK-NEXT: (block $parent (result i32)
368+
;; CHECK-NEXT: (call $nothing)
369+
;; CHECK-NEXT: (drop
370+
;; CHECK-NEXT: (br_if $parent
371+
;; CHECK-NEXT: (i32.const 2)
372+
;; CHECK-NEXT: (call $get-i32)
373+
;; CHECK-NEXT: )
374+
;; CHECK-NEXT: )
375+
;; CHECK-NEXT: (i32.const 1)
376+
;; CHECK-NEXT: )
377+
;; CHECK-NEXT: )
378+
(func $restructure-br_if-value-redundant-in-block-tail-2 (result i32)
379+
;; As above, but now the value is different, so we do not optimize
380+
(block $parent (result i32)
381+
(call $nothing)
382+
(drop
383+
(br_if $parent
384+
(i32.const 2)
385+
(call $get-i32)
386+
)
387+
)
388+
(i32.const 1)
389+
)
390+
)
391+
392+
;; CHECK: (func $restructure-br_if-value-redundant-in-block-tail-3 (type $0) (param $x i32) (result i32)
393+
;; CHECK-NEXT: (block $parent (result i32)
394+
;; CHECK-NEXT: (call $nothing)
395+
;; CHECK-NEXT: (drop
396+
;; CHECK-NEXT: (br_if $parent
397+
;; CHECK-NEXT: (call $get-i32)
398+
;; CHECK-NEXT: (call $get-i32)
399+
;; CHECK-NEXT: )
400+
;; CHECK-NEXT: )
401+
;; CHECK-NEXT: (call $get-i32)
402+
;; CHECK-NEXT: )
403+
;; CHECK-NEXT: )
404+
(func $restructure-br_if-value-redundant-in-block-tail-3 (param $x i32) (result i32)
405+
;; As above, but now the value has effects, so we do not optimize
406+
(block $parent (result i32)
407+
(call $nothing)
408+
(drop
409+
(br_if $parent
410+
(call $get-i32)
411+
(call $get-i32)
412+
)
413+
)
414+
(call $get-i32)
415+
)
416+
)
417+
418+
;; CHECK: (func $restructure-br_if-value-redundant-in-block-tail-4 (type $2) (result i32)
419+
;; CHECK-NEXT: (block $outer (result i32)
420+
;; CHECK-NEXT: (block $inner (result i32)
421+
;; CHECK-NEXT: (call $nothing)
422+
;; CHECK-NEXT: (drop
423+
;; CHECK-NEXT: (br_if $outer
424+
;; CHECK-NEXT: (i32.const 1)
425+
;; CHECK-NEXT: (call $get-i32)
426+
;; CHECK-NEXT: )
427+
;; CHECK-NEXT: )
428+
;; CHECK-NEXT: (i32.const 1)
429+
;; CHECK-NEXT: )
430+
;; CHECK-NEXT: )
431+
;; CHECK-NEXT: )
432+
(func $restructure-br_if-value-redundant-in-block-tail-4 (result i32)
433+
;; As above, but the br_if targets another block, so we do not optimize.
434+
(block $outer (result i32)
435+
(block $inner (result i32)
436+
(call $nothing)
437+
(drop
438+
(br_if $outer
439+
(i32.const 1)
440+
(call $get-i32)
441+
)
442+
)
443+
(i32.const 1)
444+
)
445+
)
446+
)
447+
448+
;; CHECK: (func $restructure-br_if-value-redundant-in-block-tail-5 (type $2) (result i32)
449+
;; CHECK-NEXT: (block $parent (result i32)
450+
;; CHECK-NEXT: (call $nothing)
451+
;; CHECK-NEXT: (br $parent
452+
;; CHECK-NEXT: (i32.const 1)
453+
;; CHECK-NEXT: )
454+
;; CHECK-NEXT: (i32.const 1)
455+
;; CHECK-NEXT: )
456+
;; CHECK-NEXT: )
457+
(func $restructure-br_if-value-redundant-in-block-tail-5 (result i32)
458+
;; As above, but the br lacks a condition. We do not bother to optimize
459+
;; the dead code after it, but also should not error here.
460+
(block $parent (result i32)
461+
(call $nothing)
462+
(br $parent
463+
(i32.const 1)
464+
)
465+
(i32.const 1)
466+
)
467+
)
468+
469+
;; CHECK: (func $restructure-select-no-multivalue (type $1)
344470
;; CHECK-NEXT: (tuple.drop 2
345-
;; CHECK-NEXT: (block $block (type $2) (result i32 i32)
471+
;; CHECK-NEXT: (block $block (type $3) (result i32 i32)
346472
;; CHECK-NEXT: (tuple.drop 2
347473
;; CHECK-NEXT: (br_if $block
348474
;; CHECK-NEXT: (tuple.make 2
@@ -387,7 +513,7 @@
387513
)
388514
)
389515

390-
;; CHECK: (func $if-of-if (type $0)
516+
;; CHECK: (func $if-of-if (type $1)
391517
;; CHECK-NEXT: (local $x i32)
392518
;; CHECK-NEXT: (if
393519
;; CHECK-NEXT: (select
@@ -421,7 +547,7 @@
421547
)
422548
)
423549

424-
;; CHECK: (func $if-of-if-but-side-effects (type $0)
550+
;; CHECK: (func $if-of-if-but-side-effects (type $1)
425551
;; CHECK-NEXT: (local $x i32)
426552
;; CHECK-NEXT: (if
427553
;; CHECK-NEXT: (local.tee $x
@@ -460,7 +586,7 @@
460586
)
461587
)
462588

463-
;; CHECK: (func $if-of-if-but-too-costly (type $0)
589+
;; CHECK: (func $if-of-if-but-too-costly (type $1)
464590
;; CHECK-NEXT: (local $x i32)
465591
;; CHECK-NEXT: (if
466592
;; CHECK-NEXT: (local.tee $x
@@ -515,7 +641,7 @@
515641
)
516642
)
517643

518-
;; CHECK: (func $if-of-if-but-inner-else (type $0)
644+
;; CHECK: (func $if-of-if-but-inner-else (type $1)
519645
;; CHECK-NEXT: (local $x i32)
520646
;; CHECK-NEXT: (if
521647
;; CHECK-NEXT: (local.tee $x
@@ -555,7 +681,7 @@
555681
)
556682
)
557683

558-
;; CHECK: (func $if-of-if-but-outer-else (type $0)
684+
;; CHECK: (func $if-of-if-but-outer-else (type $1)
559685
;; CHECK-NEXT: (local $x i32)
560686
;; CHECK-NEXT: (if
561687
;; CHECK-NEXT: (local.tee $x
@@ -595,7 +721,7 @@
595721
)
596722
)
597723

598-
;; CHECK: (func $unreachable-if (type $0)
724+
;; CHECK: (func $unreachable-if (type $1)
599725
;; CHECK-NEXT: (block $block
600726
;; CHECK-NEXT: (if (result i32)
601727
;; CHECK-NEXT: (unreachable)
@@ -625,7 +751,7 @@
625751
)
626752
)
627753

628-
;; CHECK: (func $loop-with-unreachable-if (type $0)
754+
;; CHECK: (func $loop-with-unreachable-if (type $1)
629755
;; CHECK-NEXT: (loop $label
630756
;; CHECK-NEXT: (if (result i32)
631757
;; CHECK-NEXT: (unreachable)

0 commit comments

Comments
 (0)