Skip to content

Commit e6b2164

Browse files
committed
Don't use invalidated iterators in FlattenCFGPass
Summary: FlattenCFG may erase unnecessary blocks, which also invalidates iterators to those erased blocks. Before this patch, `iterativelyFlattenCFG` could try to increment a BB iterator after that BB has been removed and crash. This patch makes FlattenCFGPass use `WeakVH` to skip over erased blocks. Reviewers: dblaikie, tstellar, davide, sanjoy, asbirlea, grosser Reviewed By: asbirlea Subscribers: hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D67672 llvm-svn: 372347
1 parent d89f2d8 commit e6b2164

File tree

2 files changed

+47
-7
lines changed

2 files changed

+47
-7
lines changed

llvm/lib/Transforms/Scalar/FlattenCFGPass.cpp

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#include "llvm/Analysis/AliasAnalysis.h"
14-
#include "llvm/Transforms/Utils/Local.h"
1514
#include "llvm/IR/CFG.h"
15+
#include "llvm/IR/ValueHandle.h"
1616
#include "llvm/Pass.h"
1717
#include "llvm/Transforms/Scalar.h"
18+
#include "llvm/Transforms/Utils/Local.h"
19+
1820
using namespace llvm;
1921

2022
#define DEBUG_TYPE "flattencfg"
@@ -52,15 +54,23 @@ FunctionPass *llvm::createFlattenCFGPass() { return new FlattenCFGPass(); }
5254
static bool iterativelyFlattenCFG(Function &F, AliasAnalysis *AA) {
5355
bool Changed = false;
5456
bool LocalChange = true;
57+
58+
// Use block handles instead of iterating over function blocks directly
59+
// to avoid using iterators invalidated by erasing blocks.
60+
std::vector<WeakVH> Blocks;
61+
Blocks.reserve(F.size());
62+
for (auto &BB : F)
63+
Blocks.push_back(&BB);
64+
5565
while (LocalChange) {
5666
LocalChange = false;
5767

58-
// Loop over all of the basic blocks and remove them if they are unneeded...
59-
//
60-
for (Function::iterator BBIt = F.begin(); BBIt != F.end();) {
61-
if (FlattenCFG(&*BBIt++, AA)) {
62-
LocalChange = true;
63-
}
68+
// Loop over all of the basic blocks and try to flatten them.
69+
for (WeakVH &BlockHandle : Blocks) {
70+
// Skip blocks erased by FlattenCFG.
71+
if (auto *BB = cast_or_null<BasicBlock>(BlockHandle))
72+
if (FlattenCFG(BB, AA))
73+
LocalChange = true;
6474
}
6575
Changed |= LocalChange;
6676
}

llvm/test/Transforms/Util/flattencfg.ll

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,33 @@ b1: ; preds = %entry, %b0
2424
exit: ; preds = %entry, %b0, %b1
2525
ret void
2626
}
27+
28+
; CHECK-LABEL: @test_not_crash2
29+
; CHECK-NEXT: entry:
30+
; CHECK-NEXT: %0 = fcmp ult float %a
31+
; CHECK-NEXT: %1 = fcmp ult float %b
32+
; CHECK-NEXT: [[COND:%[a-z0-9]+]] = or i1 %0, %1
33+
; CHECK-NEXT: br i1 [[COND]], label %bb4, label %bb3
34+
; CHECK: bb3:
35+
; CHECK-NEXT: br label %bb4
36+
; CHECK: bb4:
37+
; CHECK-NEXT: ret void
38+
define void @test_not_crash2(float %a, float %b) #0 {
39+
entry:
40+
%0 = fcmp ult float %a, 1.000000e+00
41+
br i1 %0, label %bb0, label %bb1
42+
43+
bb3: ; preds = %bb0
44+
br label %bb4
45+
46+
bb4: ; preds = %bb0, %bb3
47+
ret void
48+
49+
bb1: ; preds = %entry
50+
br label %bb0
51+
52+
bb0: ; preds = %bb1, %entry
53+
%1 = fcmp ult float %b, 1.000000e+00
54+
br i1 %1, label %bb4, label %bb3
55+
}
56+

0 commit comments

Comments
 (0)