From: David Majnemer Date: Wed, 23 Sep 2015 15:41:09 +0000 (+0000) Subject: [DeadArgElim] Split the invoke successor edge X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=6b423577e24caf97187ea16acbca64228cbe32ee [DeadArgElim] Split the invoke successor edge Invoking a function which returns an aggregate can sometimes be transformed to return a scalar value. However, this means that we need to create an insertvalue instruction(s) to recreate the correct aggregate type. We achieved this by inserting an insertvalue instruction at the invoke's normal successor. However, this is not feasible if the normal successor uses the invoke's return value inside a PHI node. Instead, split the edge between the invoke and the unwind successor and create the insertvalue instruction in the new basic block. The new basic block's successor will be the old invoke successor which leaves us with IR which is well behaved. This fixes PR24906. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@248387 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/IPO/DeadArgumentElimination.cpp b/lib/Transforms/IPO/DeadArgumentElimination.cpp index 64c5ab9cb1b..024fb2c1015 100644 --- a/lib/Transforms/IPO/DeadArgumentElimination.cpp +++ b/lib/Transforms/IPO/DeadArgumentElimination.cpp @@ -35,6 +35,7 @@ #include "llvm/Pass.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" #include #include #include @@ -967,7 +968,7 @@ bool DAE::RemoveDeadStuffFromFunction(Function *F) { Instruction *New; if (InvokeInst *II = dyn_cast(Call)) { New = InvokeInst::Create(NF, II->getNormalDest(), II->getUnwindDest(), - Args, "", Call); + Args, "", Call->getParent()); cast(New)->setCallingConv(CS.getCallingConv()); cast(New)->setAttributes(NewCallPAL); } else { @@ -997,9 +998,8 @@ bool DAE::RemoveDeadStuffFromFunction(Function *F) { " must have been a struct or an array!"); Instruction *InsertPt = Call; if (InvokeInst *II = dyn_cast(Call)) { - BasicBlock::iterator IP = II->getNormalDest()->begin(); - while (isa(IP)) ++IP; - InsertPt = IP; + BasicBlock *NewEdge = SplitEdge(New->getParent(), II->getNormalDest()); + InsertPt = NewEdge->getFirstInsertionPt(); } // We used to return a struct or array. Instead of doing smart stuff diff --git a/test/Transforms/DeadArgElim/aggregates.ll b/test/Transforms/DeadArgElim/aggregates.ll index 68d25342558..2eca76a4a4e 100644 --- a/test/Transforms/DeadArgElim/aggregates.ll +++ b/test/Transforms/DeadArgElim/aggregates.ll @@ -159,4 +159,28 @@ define internal i8 @outer() { %val = load i8, i8* %resptr ret i8 %val -} \ No newline at end of file +} + +define internal { i32 } @agg_ret() { +entry: + unreachable +} + +; CHECK-LABEL: define void @PR24906 +; CHECK: %[[invoke:.*]] = invoke i32 @agg_ret() +; CHECK: %[[oldret:.*]] = insertvalue { i32 } undef, i32 %[[invoke]], 0 +; CHECK: phi { i32 } [ %[[oldret]], +define void @PR24906() personality i32 (i32)* undef { +entry: + %tmp2 = invoke { i32 } @agg_ret() + to label %bb3 unwind label %bb4 + +bb3: + %tmp3 = phi { i32 } [ %tmp2, %entry ] + unreachable + +bb4: + %tmp4 = landingpad { i8*, i32 } + cleanup + unreachable +}