From a9cd579599505f4547ef5371e43a1ef41351b734 Mon Sep 17 00:00:00 2001 From: Jakub Kuderski Date: Thu, 19 Sep 2019 19:39:42 +0000 Subject: [PATCH] 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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@372347 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/FlattenCFGPass.cpp | 24 +++++++++++++------ test/Transforms/Util/flattencfg.ll | 30 ++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/lib/Transforms/Scalar/FlattenCFGPass.cpp b/lib/Transforms/Scalar/FlattenCFGPass.cpp index 31670b1464e..e6abf1ceb02 100644 --- a/lib/Transforms/Scalar/FlattenCFGPass.cpp +++ b/lib/Transforms/Scalar/FlattenCFGPass.cpp @@ -11,10 +11,12 @@ //===----------------------------------------------------------------------===// #include "llvm/Analysis/AliasAnalysis.h" -#include "llvm/Transforms/Utils/Local.h" #include "llvm/IR/CFG.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Pass.h" #include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Utils/Local.h" + using namespace llvm; #define DEBUG_TYPE "flattencfg" @@ -52,15 +54,23 @@ FunctionPass *llvm::createFlattenCFGPass() { return new FlattenCFGPass(); } static bool iterativelyFlattenCFG(Function &F, AliasAnalysis *AA) { bool Changed = false; bool LocalChange = true; + + // Use block handles instead of iterating over function blocks directly + // to avoid using iterators invalidated by erasing blocks. + std::vector Blocks; + Blocks.reserve(F.size()); + for (auto &BB : F) + Blocks.push_back(&BB); + while (LocalChange) { LocalChange = false; - // Loop over all of the basic blocks and remove them if they are unneeded... - // - for (Function::iterator BBIt = F.begin(); BBIt != F.end();) { - if (FlattenCFG(&*BBIt++, AA)) { - LocalChange = true; - } + // Loop over all of the basic blocks and try to flatten them. + for (WeakVH &BlockHandle : Blocks) { + // Skip blocks erased by FlattenCFG. + if (auto *BB = cast_or_null(BlockHandle)) + if (FlattenCFG(BB, AA)) + LocalChange = true; } Changed |= LocalChange; } diff --git a/test/Transforms/Util/flattencfg.ll b/test/Transforms/Util/flattencfg.ll index 4fcb77ab023..1814d6e1f8e 100644 --- a/test/Transforms/Util/flattencfg.ll +++ b/test/Transforms/Util/flattencfg.ll @@ -24,3 +24,33 @@ b1: ; preds = %entry, %b0 exit: ; preds = %entry, %b0, %b1 ret void } + +; CHECK-LABEL: @test_not_crash2 +; CHECK-NEXT: entry: +; CHECK-NEXT: %0 = fcmp ult float %a +; CHECK-NEXT: %1 = fcmp ult float %b +; CHECK-NEXT: [[COND:%[a-z0-9]+]] = or i1 %0, %1 +; CHECK-NEXT: br i1 [[COND]], label %bb4, label %bb3 +; CHECK: bb3: +; CHECK-NEXT: br label %bb4 +; CHECK: bb4: +; CHECK-NEXT: ret void +define void @test_not_crash2(float %a, float %b) #0 { +entry: + %0 = fcmp ult float %a, 1.000000e+00 + br i1 %0, label %bb0, label %bb1 + +bb3: ; preds = %bb0 + br label %bb4 + +bb4: ; preds = %bb0, %bb3 + ret void + +bb1: ; preds = %entry + br label %bb0 + +bb0: ; preds = %bb1, %entry + %1 = fcmp ult float %b, 1.000000e+00 + br i1 %1, label %bb4, label %bb3 +} + -- 2.50.1