Skip to content

Commit 9bd8871

Browse files
RemoveUnusedBrs: Optimize breaks with constant fallthroughs (#7639)
Fixes: #7637
1 parent da6c937 commit 9bd8871

9 files changed

+292
-133
lines changed

src/passes/RemoveUnusedBrs.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
#include "ir/effects.h"
2525
#include "ir/gc-type-utils.h"
2626
#include "ir/literal-utils.h"
27+
#include "ir/localize.h"
28+
#include "ir/properties.h"
2729
#include "ir/utils.h"
2830
#include "parsing.h"
2931
#include "pass.h"
@@ -1881,6 +1883,36 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
18811883
start = end;
18821884
}
18831885
}
1886+
1887+
void visitBreak(Break* curr) {
1888+
if (!curr->condition) {
1889+
return;
1890+
}
1891+
auto* value = Properties::getFallthrough(
1892+
curr->condition, passOptions, *getModule());
1893+
// Optimize if condition's fallthrough is a constant.
1894+
if (auto* c = value->dynCast<Const>()) {
1895+
ChildLocalizer localizer(
1896+
curr, getFunction(), *getModule(), passOptions);
1897+
auto* block = localizer.getChildrenReplacement();
1898+
if (c->value.geti32()) {
1899+
// the branch is always taken, make it unconditional
1900+
curr->condition = nullptr;
1901+
curr->type = Type::unreachable;
1902+
block->list.push_back(curr);
1903+
block->finalize();
1904+
// The type changed, so refinalize.
1905+
refinalize = true;
1906+
} else {
1907+
// the branch is never taken, allow control flow to fall through
1908+
if (curr->value) {
1909+
block->list.push_back(curr->value);
1910+
block->finalize();
1911+
}
1912+
}
1913+
replaceCurrent(block);
1914+
}
1915+
}
18841916
};
18851917
FinalOptimizer finalOptimizer(getPassOptions());
18861918
finalOptimizer.setModule(getModule());

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

Lines changed: 108 additions & 6 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 $4) (param $x i32) (result anyref)
8+
;; CHECK: (func $selectify-fresh-lub (type $5) (param $x i32) (result anyref)
99
;; CHECK-NEXT: (select (result i31ref)
1010
;; CHECK-NEXT: (ref.null none)
1111
;; CHECK-NEXT: (ref.i31
@@ -340,6 +340,106 @@
340340
)
341341
)
342342

343+
;; CHECK: (func $restructure-br_if-constant-branch-1 (type $3) (param $x i32)
344+
;; CHECK-NEXT: (local $1 i32)
345+
;; CHECK-NEXT: (drop
346+
;; CHECK-NEXT: (block $x (result i32)
347+
;; CHECK-NEXT: (drop
348+
;; CHECK-NEXT: (block
349+
;; CHECK-NEXT: (local.set $1
350+
;; CHECK-NEXT: (local.tee $x
351+
;; CHECK-NEXT: (i32.const 42)
352+
;; CHECK-NEXT: )
353+
;; CHECK-NEXT: )
354+
;; CHECK-NEXT: (br $x
355+
;; CHECK-NEXT: (i32.const 10)
356+
;; CHECK-NEXT: )
357+
;; CHECK-NEXT: )
358+
;; CHECK-NEXT: )
359+
;; CHECK-NEXT: (i32.const 20)
360+
;; CHECK-NEXT: )
361+
;; CHECK-NEXT: )
362+
;; CHECK-NEXT: (drop
363+
;; CHECK-NEXT: (block $x0 (result i32)
364+
;; CHECK-NEXT: (drop
365+
;; CHECK-NEXT: (block (result i32)
366+
;; CHECK-NEXT: (i32.const 10)
367+
;; CHECK-NEXT: )
368+
;; CHECK-NEXT: )
369+
;; CHECK-NEXT: (i32.const 20)
370+
;; CHECK-NEXT: )
371+
;; CHECK-NEXT: )
372+
;; CHECK-NEXT: )
373+
(func $restructure-br_if-constant-branch-1 (param $x i32)
374+
;; We can see a nonzero constant falls through the tee, so this br always happens.
375+
(drop
376+
(block $x (result i32)
377+
(drop
378+
(br_if $x
379+
(i32.const 10)
380+
(local.tee $x
381+
(i32.const 42)
382+
)
383+
)
384+
)
385+
(i32.const 20)
386+
)
387+
)
388+
;; We can see the zero condition, so just let the control flow fall through.
389+
(drop
390+
(block $x (result i32)
391+
(drop
392+
(br_if $x
393+
(i32.const 10)
394+
(i32.const 0)
395+
)
396+
)
397+
(i32.const 20)
398+
)
399+
)
400+
)
401+
;; CHECK: (func $restructure-br_if-constant-branch-2 (type $3) (param $x i32)
402+
;; CHECK-NEXT: (local $1 i32)
403+
;; CHECK-NEXT: (local $2 i32)
404+
;; CHECK-NEXT: (block $x
405+
;; CHECK-NEXT: (block
406+
;; CHECK-NEXT: (local.set $1
407+
;; CHECK-NEXT: (local.tee $x
408+
;; CHECK-NEXT: (i32.const 1)
409+
;; CHECK-NEXT: )
410+
;; CHECK-NEXT: )
411+
;; CHECK-NEXT: (br $x)
412+
;; CHECK-NEXT: )
413+
;; CHECK-NEXT: )
414+
;; CHECK-NEXT: (block $x0
415+
;; CHECK-NEXT: (block
416+
;; CHECK-NEXT: (local.set $2
417+
;; CHECK-NEXT: (local.tee $x
418+
;; CHECK-NEXT: (i32.const 0)
419+
;; CHECK-NEXT: )
420+
;; CHECK-NEXT: )
421+
;; CHECK-NEXT: )
422+
;; CHECK-NEXT: )
423+
;; CHECK-NEXT: )
424+
(func $restructure-br_if-constant-branch-2 (param $x i32)
425+
;; as before, but now there is no value.
426+
(block $x
427+
(br_if $x
428+
(local.tee $x
429+
(i32.const 1)
430+
)
431+
)
432+
)
433+
(block $x
434+
(br_if $x
435+
(local.tee $x
436+
(i32.const 0)
437+
)
438+
)
439+
)
440+
)
441+
442+
343443
;; CHECK: (func $restructure-br_if-value-redundant-in-block-tail-1 (type $2) (result i32)
344444
;; CHECK-NEXT: (block $parent (result i32)
345445
;; CHECK-NEXT: (call $nothing)
@@ -473,7 +573,7 @@
473573
;; CHECK-NEXT: (br_if $block
474574
;; CHECK-NEXT: (local.get $temp)
475575
;; CHECK-NEXT: (local.tee $temp
476-
;; CHECK-NEXT: (i32.const 1)
576+
;; CHECK-NEXT: (local.get $temp)
477577
;; CHECK-NEXT: )
478578
;; CHECK-NEXT: )
479579
;; CHECK-NEXT: )
@@ -489,7 +589,7 @@
489589
(br_if $block
490590
(local.get $temp)
491591
(local.tee $temp
492-
(i32.const 1)
592+
(local.get $temp)
493593
)
494594
)
495595
)
@@ -498,8 +598,9 @@
498598
)
499599

500600
;; CHECK: (func $restructure-select-no-multivalue (type $1)
601+
;; CHECK-NEXT: (local $x i32)
501602
;; CHECK-NEXT: (tuple.drop 2
502-
;; CHECK-NEXT: (block $block (type $3) (result i32 i32)
603+
;; CHECK-NEXT: (block $block (type $4) (result i32 i32)
503604
;; CHECK-NEXT: (tuple.drop 2
504605
;; CHECK-NEXT: (br_if $block
505606
;; CHECK-NEXT: (tuple.make 2
@@ -508,7 +609,7 @@
508609
;; CHECK-NEXT: (i32.const 2)
509610
;; CHECK-NEXT: )
510611
;; CHECK-NEXT: )
511-
;; CHECK-NEXT: (i32.const 3)
612+
;; CHECK-NEXT: (local.get $x)
512613
;; CHECK-NEXT: )
513614
;; CHECK-NEXT: )
514615
;; CHECK-NEXT: (tuple.make 2
@@ -519,6 +620,7 @@
519620
;; CHECK-NEXT: )
520621
;; CHECK-NEXT: )
521622
(func $restructure-select-no-multivalue
623+
(local $x i32)
522624
(tuple.drop 2
523625
(block $block (result i32 i32)
524626
(tuple.drop 2
@@ -533,7 +635,7 @@
533635
(i32.const 2)
534636
)
535637
)
536-
(i32.const 3)
638+
(local.get $x)
537639
)
538640
)
539641
(tuple.make 2

test/lit/passes/remove-unused-brs_all-features.wast

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,10 @@
6464
)
6565

6666
;; CHECK: (func $test-prefinalize (type $4) (result f64)
67+
;; CHECK-NEXT: (local $x i32)
6768
;; CHECK-NEXT: (loop $loop (result f64)
6869
;; CHECK-NEXT: (if (result f64)
69-
;; CHECK-NEXT: (i32.const 1)
70+
;; CHECK-NEXT: (local.get $x)
7071
;; CHECK-NEXT: (then
7172
;; CHECK-NEXT: (f64.const 0)
7273
;; CHECK-NEXT: )
@@ -85,12 +86,13 @@
8586
;; CHECK-NEXT: )
8687
;; CHECK-NEXT: )
8788
(func $test-prefinalize (result f64)
89+
(local $x i32)
8890
(loop $loop (result f64)
8991
(block $block (result f64)
9092
(drop
9193
(br_if $block
9294
(f64.const 0)
93-
(i32.const 1)
95+
(local.get $x)
9496
)
9597
)
9698
(if

0 commit comments

Comments
 (0)