From 80269962da6b3368009cb0376ee320e71eaf0a5a Mon Sep 17 00:00:00 2001 From: Brendon Cahoon Date: Mon, 17 Apr 2017 19:11:04 +0000 Subject: [PATCH] [CodeGenPrepare] Fix crash due to an invalid CFG The splitIndirectCriticalEdges function generates and invalid CFG when the 'Target' basic block is a loop to itself. When this occurs, the code that updates the predecessor terminator needs to update the terminator in the split basic block. This occurs when there is an edge from block D back to D. Since D is split in to D0 and D1, the code needs to update the terminator in D1. But D1 is not in the OtherPreds vector, so it was not getting updated. Differential Revision: https://reviews.llvm.org/D32126 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@300480 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CodeGenPrepare.cpp | 10 ++++- .../CodeGenPrepare/split-indirect-loop.ll | 37 +++++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 test/Transforms/CodeGenPrepare/split-indirect-loop.ll diff --git a/lib/CodeGen/CodeGenPrepare.cpp b/lib/CodeGen/CodeGenPrepare.cpp index 2bdd189557b..aa0be910e3b 100644 --- a/lib/CodeGen/CodeGenPrepare.cpp +++ b/lib/CodeGen/CodeGenPrepare.cpp @@ -570,8 +570,14 @@ bool CodeGenPrepare::splitIndirectCriticalEdges(Function &F) { ValueToValueMapTy VMap; BasicBlock *DirectSucc = CloneBasicBlock(Target, VMap, ".clone", &F); - for (BasicBlock *Pred : OtherPreds) - Pred->getTerminator()->replaceUsesOfWith(Target, DirectSucc); + for (BasicBlock *Pred : OtherPreds) { + // If the target is a loop to itself, then the terminator of the split + // block needs to be updated. + if (Pred == Target) + BodyBlock->getTerminator()->replaceUsesOfWith(Target, DirectSucc); + else + Pred->getTerminator()->replaceUsesOfWith(Target, DirectSucc); + } // Ok, now fix up the PHIs. We know the two blocks only have PHIs, and that // they are clones, so the number of PHIs are the same. diff --git a/test/Transforms/CodeGenPrepare/split-indirect-loop.ll b/test/Transforms/CodeGenPrepare/split-indirect-loop.ll new file mode 100644 index 00000000000..cb834bb5dd8 --- /dev/null +++ b/test/Transforms/CodeGenPrepare/split-indirect-loop.ll @@ -0,0 +1,37 @@ +; RUN: opt -codegenprepare -S < %s | FileCheck %s + +; Test that an invalid CFG is not created by splitIndirectCriticalEdges +; transformation when the 'target' block is a loop to itself. + +; CHECK: .split: +; CHECK: br label %while.body.clone +; CHECK: if.else1: +; CHECK: indirectbr +; CHECK: while.body.clone: +; CHECK: br label %.split + +define void @test() { +entry: + br label %if.else + +if.else: + br i1 undef, label %while.body, label %preheader + +preheader: + br label %if.else1 + +if.then: + unreachable + +while.body: + %dest.sroa = phi i32 [ %1, %while.body ], [ undef, %if.else1 ], [ undef, %if.else ] + %0 = inttoptr i32 %dest.sroa to i8* + %incdec.ptr = getelementptr inbounds i8, i8* %0, i32 -1 + %1 = ptrtoint i8* %incdec.ptr to i32 + store i8 undef, i8* %incdec.ptr, align 1 + br label %while.body + +if.else1: + indirectbr i8* undef, [label %if.then, label %while.body, label %if.else, label %if.else1] +} + -- 2.40.0