From 14e545d18e46187b0f02e7c705a3da3ad82225c2 Mon Sep 17 00:00:00 2001 From: Dale Johannesen Date: Thu, 6 Aug 2009 22:56:40 +0000 Subject: [PATCH] Fix PR 4626, a crash in branch folding after OptimizeBlock produced a CFG it wasn't prepared for. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78351 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/BranchFolding.cpp | 18 +++- .../X86/2009-08-06-branchfolder-crash.ll | 90 +++++++++++++++++++ 2 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 test/CodeGen/X86/2009-08-06-branchfolder-crash.ll diff --git a/lib/CodeGen/BranchFolding.cpp b/lib/CodeGen/BranchFolding.cpp index 193bbb610f7..d25152b1e43 100644 --- a/lib/CodeGen/BranchFolding.cpp +++ b/lib/CodeGen/BranchFolding.cpp @@ -893,8 +893,24 @@ void BranchFolder::OptimizeBlock(MachineBasicBlock *MBB) { while (!MBB->pred_empty()) { MachineBasicBlock *Pred = *(MBB->pred_end()-1); Pred->ReplaceUsesOfBlockWith(MBB, FallThrough); + // If this resulted in a predecessor with true and false edges + // both going to the fallthrough block, clean up; + // BranchFolding doesn't like this. + MachineBasicBlock::succ_iterator SI = Pred->succ_begin(); + bool found = false; + while (SI != Pred->succ_end()) { + if (*SI == FallThrough) { + if (!found) { + found = true; + ++SI; + } else { + SI = Pred->removeSuccessor(SI); + } + } else { + ++SI; + } + } } - // If MBB was the target of a jump table, update jump tables to go to the // fallthrough instead. MBB->getParent()->getJumpTableInfo()-> diff --git a/test/CodeGen/X86/2009-08-06-branchfolder-crash.ll b/test/CodeGen/X86/2009-08-06-branchfolder-crash.ll new file mode 100644 index 00000000000..5e58725cb99 --- /dev/null +++ b/test/CodeGen/X86/2009-08-06-branchfolder-crash.ll @@ -0,0 +1,90 @@ +; RUN: llvm-as < %s | llc -O3 +; PR4626 +; ModuleID = '' +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32" +target triple = "i386-pc-linux-gnu" +@g_3 = common global i8 0, align 1 ; [#uses=2] + +define signext i8 @safe_mul_func_int16_t_s_s(i32 %_si1, i8 signext %_si2) nounwind readnone { +entry: + %tobool = icmp eq i32 %_si1, 0 ; [#uses=1] + %cmp = icmp sgt i8 %_si2, 0 ; [#uses=2] + %or.cond = or i1 %cmp, %tobool ; [#uses=1] + br i1 %or.cond, label %lor.rhs, label %land.lhs.true3 + +land.lhs.true3: ; preds = %entry + %conv5 = sext i8 %_si2 to i32 ; [#uses=1] + %cmp7 = icmp slt i32 %conv5, %_si1 ; [#uses=1] + br i1 %cmp7, label %cond.end, label %lor.rhs + +lor.rhs: ; preds = %land.lhs.true3, %entry + %cmp10.not = icmp slt i32 %_si1, 1 ; [#uses=1] + %or.cond23 = and i1 %cmp, %cmp10.not ; [#uses=1] + br i1 %or.cond23, label %lor.end, label %cond.false + +lor.end: ; preds = %lor.rhs + %tobool19 = icmp ne i8 %_si2, 0 ; [#uses=2] + %lor.ext = zext i1 %tobool19 to i32 ; [#uses=1] + br i1 %tobool19, label %cond.end, label %cond.false + +cond.false: ; preds = %lor.end, %lor.rhs + %conv21 = sext i8 %_si2 to i32 ; [#uses=1] + br label %cond.end + +cond.end: ; preds = %cond.false, %lor.end, %land.lhs.true3 + %cond = phi i32 [ %conv21, %cond.false ], [ 1, %land.lhs.true3 ], [ %lor.ext, %lor.end ] ; [#uses=1] + %conv22 = trunc i32 %cond to i8 ; [#uses=1] + ret i8 %conv22 +} + +define i32 @func_34(i8 signext %p_35) nounwind readonly { +entry: + %tobool = icmp eq i8 %p_35, 0 ; [#uses=1] + br i1 %tobool, label %lor.lhs.false, label %if.then + +lor.lhs.false: ; preds = %entry + %tmp1 = load i8* @g_3 ; [#uses=1] + %tobool3 = icmp eq i8 %tmp1, 0 ; [#uses=1] + br i1 %tobool3, label %return, label %if.then + +if.then: ; preds = %lor.lhs.false, %entry + %tmp4 = load i8* @g_3 ; [#uses=1] + %conv5 = sext i8 %tmp4 to i32 ; [#uses=1] + ret i32 %conv5 + +return: ; preds = %lor.lhs.false + ret i32 0 +} + +define void @foo(i32 %p_5) noreturn nounwind { +entry: + %cmp = icmp sgt i32 %p_5, 0 ; [#uses=2] + %call = tail call i32 @safe() nounwind ; [#uses=1] + %conv1 = trunc i32 %call to i8 ; [#uses=3] + %tobool.i = xor i1 %cmp, true ; [#uses=3] + %cmp.i = icmp sgt i8 %conv1, 0 ; [#uses=3] + %or.cond.i = or i1 %cmp.i, %tobool.i ; [#uses=1] + br i1 %or.cond.i, label %lor.rhs.i, label %land.lhs.true3.i + +land.lhs.true3.i: ; preds = %entry + %xor = zext i1 %cmp to i32 ; [#uses=1] + %conv5.i = sext i8 %conv1 to i32 ; [#uses=1] + %cmp7.i = icmp slt i32 %conv5.i, %xor ; [#uses=1] + %cmp7.i.not = xor i1 %cmp7.i, true ; [#uses=1] + %or.cond23.i = and i1 %cmp.i, %tobool.i ; [#uses=1] + %or.cond = and i1 %cmp7.i.not, %or.cond23.i ; [#uses=1] + br i1 %or.cond, label %lor.end.i, label %for.inc + +lor.rhs.i: ; preds = %entry + %or.cond23.i.old = and i1 %cmp.i, %tobool.i ; [#uses=1] + br i1 %or.cond23.i.old, label %lor.end.i, label %for.inc + +lor.end.i: ; preds = %lor.rhs.i, %land.lhs.true3.i + %tobool19.i = icmp eq i8 %conv1, 0 ; [#uses=0] + br label %for.inc + +for.inc: ; preds = %for.inc, %lor.end.i, %lor.rhs.i, %land.lhs.true3.i + br label %for.inc +} + +declare i32 @safe()