forked from OSchip/llvm-project
[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:
parent
2a6c13274c
commit
fa36bde2f6
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue