22
22
#include " llvm/IR/Attributes.h"
23
23
#include " llvm/IR/CFG.h"
24
24
#include " llvm/IR/Instructions.h"
25
- #include " llvm/Transforms/Utils/BasicBlockUtils.h"
26
25
#include " llvm/Transforms/Utils/Cloning.h"
27
26
28
27
using namespace llvm ;
@@ -55,7 +54,7 @@ static void rewriteFuncWithReturnType(Function &OldF, Value *NewRetValue) {
55
54
BasicBlock *NewRetBlock = NewRetI ? NewRetI->getParent () : &EntryBB;
56
55
57
56
BasicBlock::iterator NewValIt =
58
- NewRetI ? NewRetI->getIterator () : EntryBB.end ();
57
+ NewRetI ? std::next ( NewRetI->getIterator ()) : EntryBB.begin ();
59
58
60
59
Type *OldRetTy = OldFuncTy->getReturnType ();
61
60
@@ -73,28 +72,16 @@ static void rewriteFuncWithReturnType(Function &OldF, Value *NewRetValue) {
73
72
}
74
73
}
75
74
76
- // Now prune any CFG edges we have to deal with.
77
- //
78
- // Use KeepOneInputPHIs in case the instruction we are using for the return is
79
- // that phi.
80
- // TODO: Could avoid this with fancier iterator management.
81
- for (BasicBlock *Succ : successors (NewRetBlock))
82
- Succ->removePredecessor (NewRetBlock, /* KeepOneInputPHIs=*/ true );
83
-
84
- // Now delete the tail of this block, in reverse to delete uses before defs.
85
- for (Instruction &I : make_early_inc_range (
86
- make_range (NewRetBlock->rbegin (), NewValIt.getReverse ()))) {
87
- Value *Replacement = getDefaultValue (I.getType ());
88
- I.replaceAllUsesWith (Replacement);
89
- I.eraseFromParent ();
90
- }
75
+ // If we're returning an instruction, split the basic block so we can let
76
+ // EliminateUnreachableBlocks cleanup the successors.
77
+ BasicBlock *TailBB = NewRetBlock->splitBasicBlock (NewValIt);
91
78
79
+ // Replace the unconditional branch splitBasicBlock created
80
+ NewRetBlock->getTerminator ()->eraseFromParent ();
92
81
ReturnInst::Create (Ctx, NewRetValue, NewRetBlock);
93
82
94
- // TODO: We may be eliminating blocks that were originally unreachable. We
95
- // probably ought to only be pruning blocks that became dead directly as a
96
- // result of our pruning here.
97
- EliminateUnreachableBlocks (OldF);
83
+ // Now prune any CFG edges we have to deal with.
84
+ simpleSimplifyCFG (OldF, {TailBB}, /* FoldBlockIntoPredecessor=*/ false );
98
85
99
86
// Drop the incompatible attributes before we copy over to the new function.
100
87
if (OldRetTy != NewRetTy) {
@@ -199,20 +186,6 @@ static bool shouldReplaceNonVoidReturnValue(const BasicBlock &BB,
199
186
return true ;
200
187
}
201
188
202
- static bool canHandleSuccessors (const BasicBlock &BB) {
203
- // TODO: Handle invoke and other exotic terminators
204
- if (!isa<ReturnInst, UnreachableInst, BranchInst, SwitchInst>(
205
- BB.getTerminator ()))
206
- return false ;
207
-
208
- for (const BasicBlock *Succ : successors (&BB)) {
209
- if (!Succ->canSplitPredecessors ())
210
- return false ;
211
- }
212
-
213
- return true ;
214
- }
215
-
216
189
static bool shouldForwardValueToReturn (const BasicBlock &BB, const Value *V,
217
190
Type *RetTy) {
218
191
if (!isReallyValidReturnType (V->getType ()))
@@ -231,10 +204,9 @@ static bool tryForwardingInstructionsToReturn(
231
204
Type *RetTy = F.getReturnType ();
232
205
233
206
for (BasicBlock &BB : F) {
234
- if (!canHandleSuccessors (BB))
235
- continue ;
236
-
237
- for (Instruction &I : BB) {
207
+ // Skip the terminator, we can't insert a second terminator to return its
208
+ // value.
209
+ for (Instruction &I : make_range (BB.begin (), std::prev (BB.end ()))) {
238
210
if (shouldForwardValueToReturn (BB, &I, RetTy) && !O.shouldKeep ()) {
239
211
FuncsToReplace.emplace_back (&F, &I);
240
212
return true ;
0 commit comments