[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.

llvm-svn: 248387
This commit is contained in:
David Majnemer 2015-09-23 15:41:09 +00:00
parent 2a6c13274c
commit fa36bde2f6
2 changed files with 29 additions and 5 deletions

View File

@ -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 <map>
#include <set>
#include <tuple>
@ -967,7 +968,7 @@ bool DAE::RemoveDeadStuffFromFunction(Function *F) {
Instruction *New;
if (InvokeInst *II = dyn_cast<InvokeInst>(Call)) {
New = InvokeInst::Create(NF, II->getNormalDest(), II->getUnwindDest(),
Args, "", Call);
Args, "", Call->getParent());
cast<InvokeInst>(New)->setCallingConv(CS.getCallingConv());
cast<InvokeInst>(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<InvokeInst>(Call)) {
BasicBlock::iterator IP = II->getNormalDest()->begin();
while (isa<PHINode>(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

View File

@ -159,4 +159,28 @@ define internal i8 @outer() {
%val = load i8, i8* %resptr
ret i8 %val
}
}
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
}