Skip to content

Commit 5f252c3

Browse files
hobby8kripken
authored andcommitted
Fix bug and leak in relooper merge consecutive blocks (#2159)
Fixes in Relooper merge consecutive blocks: Entry block getting removed when it is part of a loop: bb1->AddBranchTo(bb2, nullptr); bb1->AddBranchTo(bb3, ...); bb2->AddBranchTo(bb1, nullptr); bb3->AddBranchTo(bb4, nullptr); relooper.AddBlock(bb1); relooper.AddBlock(bb2); relooper.AddBlock(bb3); relooper.AddBlock(bb4); relooper.Calculate(bb1); Branches memory leak
1 parent 1578cec commit 5f252c3

3 files changed

Lines changed: 95 additions & 2 deletions

File tree

src/cfg/Relooper.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,10 @@ struct Liveness : public RelooperRecursor {
533533
typedef std::pair<Branch*, Block*> BranchBlock;
534534

535535
struct Optimizer : public RelooperRecursor {
536-
Optimizer(Relooper* Parent) : RelooperRecursor(Parent) {
536+
Block* Entry;
537+
538+
Optimizer(Relooper* Parent, Block* EntryInit)
539+
: RelooperRecursor(Parent), Entry(EntryInit) {
537540
// TODO: there are likely some rare but possible O(N^2) cases with this
538541
// looping
539542
bool More = true;
@@ -726,6 +729,7 @@ struct Optimizer : public RelooperRecursor {
726729
NumPredecessors[NextBlock]++;
727730
}
728731
}
732+
NumPredecessors[Entry]++;
729733
for (auto* CurrBlock : Parent->Blocks) {
730734
if (CurrBlock->BranchesOut.size() == 1) {
731735
auto iter = CurrBlock->BranchesOut.begin();
@@ -744,6 +748,9 @@ struct Optimizer : public RelooperRecursor {
744748
Builder.makeSequence(CurrBlock->Code, NextBlock->Code);
745749
// Use the next block's branching behavior
746750
CurrBlock->BranchesOut.swap(NextBlock->BranchesOut);
751+
for (auto& iter : NextBlock->BranchesOut) {
752+
delete iter.second;
753+
}
747754
NextBlock->BranchesOut.clear();
748755
CurrBlock->SwitchCondition = NextBlock->SwitchCondition;
749756
// The next block now has no predecessors.
@@ -1032,7 +1039,7 @@ struct Optimizer : public RelooperRecursor {
10321039

10331040
void Relooper::Calculate(Block* Entry) {
10341041
// Optimize.
1035-
Optimizer(this);
1042+
Optimizer(this, Entry);
10361043

10371044
// Find live blocks.
10381045
Liveness Live(this);

test/example/relooper-merge7.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
2+
#include <assert.h>
3+
#include <stdio.h>
4+
5+
#include "binaryen-c.h"
6+
7+
int main() {
8+
BinaryenModuleRef module = BinaryenModuleCreate();
9+
10+
RelooperRef relooper = RelooperCreate(module);
11+
12+
// Create the basic blocks
13+
RelooperBlockRef b[4];
14+
int hasTerminator[4] = {0, 0, 0, 1};
15+
16+
int numBlocks = sizeof(b) / sizeof(RelooperBlockRef);
17+
assert(sizeof(hasTerminator) / sizeof(int) == numBlocks);
18+
int i;
19+
for (i = 0; i < numBlocks; i++) {
20+
BinaryenExpressionRef args[] = {
21+
BinaryenConst(module, BinaryenLiteralInt32(i))};
22+
BinaryenExpressionRef list[] = {
23+
BinaryenCall(module, "print", args, 1, BinaryenTypeNone()),
24+
BinaryenReturn(module, NULL) // relevant only if hasTerminator[i]
25+
};
26+
b[i] = RelooperAddBlock(
27+
relooper,
28+
BinaryenBlock(
29+
module, NULL, list, 1 + hasTerminator[i], BinaryenTypeNone()));
30+
}
31+
32+
// Create the branches.
33+
// In this testcase, only b[2] and b[3] can be merged.
34+
RelooperAddBranch(b[0], b[1], NULL, NULL);
35+
RelooperAddBranch(
36+
b[0], b[2], BinaryenConst(module, BinaryenLiteralInt32(-10)), NULL);
37+
RelooperAddBranch(b[1], b[0], NULL, NULL);
38+
RelooperAddBranch(b[2], b[3], NULL, NULL);
39+
40+
BinaryenExpressionRef all = RelooperRenderAndDispose(relooper, b[0], 1);
41+
42+
// Print it out
43+
BinaryenExpressionPrint(all);
44+
45+
// Clean up the module, which owns all the objects we created above
46+
BinaryenModuleDispose(module);
47+
48+
return 0;
49+
}

test/example/relooper-merge7.txt

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
(block
2+
(block $block$3$break
3+
(loop $shape$0$continue
4+
(block $block$2$break
5+
(call $print
6+
(i32.const 0)
7+
)
8+
(if
9+
(i32.const -10)
10+
(br $block$3$break)
11+
(br $block$2$break)
12+
)
13+
)
14+
(block
15+
(call $print
16+
(i32.const 1)
17+
)
18+
(block
19+
(br $shape$0$continue)
20+
)
21+
)
22+
)
23+
)
24+
(block
25+
(block
26+
(call $print
27+
(i32.const 2)
28+
)
29+
(block
30+
(call $print
31+
(i32.const 3)
32+
)
33+
(return)
34+
)
35+
)
36+
)
37+
)

0 commit comments

Comments
 (0)