@@ -40,17 +40,18 @@ static bool isReallyValidReturnType(Type *Ty) {
4040}
4141
4242// / Insert a ret inst after \p NewRetValue, which returns the value it produces.
43- static void rewriteFuncWithReturnType (Function &OldF,
44- Instruction *NewRetValue) {
43+ static void rewriteFuncWithReturnType (Function &OldF, Value *NewRetValue) {
4544 Type *NewRetTy = NewRetValue->getType ();
4645 FunctionType *OldFuncTy = OldF.getFunctionType ();
4746
4847 FunctionType *NewFuncTy =
4948 FunctionType::get (NewRetTy, OldFuncTy->params (), OldFuncTy->isVarArg ());
5049
5150 LLVMContext &Ctx = OldF.getContext ();
51+ Instruction *NewRetI = cast<Instruction>(NewRetValue);
52+ BasicBlock *NewRetBlock = NewRetI->getParent ();
5253
53- BasicBlock *NewRetBlock = NewRetValue-> getParent ();
54+ BasicBlock::iterator NewValIt = NewRetI-> getIterator ();
5455
5556 // Hack up any return values in other blocks, we can't leave them as ret void.
5657 if (OldFuncTy->getReturnType ()->isVoidTy ()) {
@@ -75,8 +76,8 @@ static void rewriteFuncWithReturnType(Function &OldF,
7576 Succ->removePredecessor (NewRetBlock, /* KeepOneInputPHIs=*/ true );
7677
7778 // Now delete the tail of this block, in reverse to delete uses before defs.
78- for (Instruction &I : make_early_inc_range (make_range (
79- NewRetBlock->rbegin (), NewRetValue-> getIterator () .getReverse ()))) {
79+ for (Instruction &I : make_early_inc_range (
80+ make_range ( NewRetBlock->rbegin (), NewValIt .getReverse ()))) {
8081
8182 Value *Replacement = getDefaultValue (I.getType ());
8283 I.replaceAllUsesWith (Replacement);
@@ -193,12 +194,19 @@ static bool canHandleSuccessors(const BasicBlock &BB) {
193194 return true ;
194195}
195196
196- static bool tryForwardingValuesToReturn (
197- Function &F, Oracle &O,
198- std::vector<std::pair<Function *, Instruction *>> &FuncsToReplace) {
197+ static bool shouldForwardValueToReturn (const BasicBlock &BB, const Value *V,
198+ Type *RetTy) {
199+ if (!isReallyValidReturnType (V->getType ()))
200+ return false ;
201+
202+ return (RetTy->isVoidTy () ||
203+ (RetTy == V->getType () && shouldReplaceNonVoidReturnValue (BB, V))) &&
204+ canReplaceFuncUsers (*BB.getParent (), V->getType ());
205+ }
199206
200- // TODO: Should this try to forward arguments to the return value before
201- // instructions?
207+ static bool tryForwardingInstructionsToReturn (
208+ Function &F, Oracle &O,
209+ std::vector<std::pair<Function *, Value *>> &FuncsToReplace) {
202210
203211 // TODO: Should we try to expand returns to aggregate for function that
204212 // already have a return value?
@@ -209,12 +217,7 @@ static bool tryForwardingValuesToReturn(
209217 continue ;
210218
211219 for (Instruction &I : BB) {
212- if (!isReallyValidReturnType (I.getType ()))
213- continue ;
214-
215- if ((RetTy->isVoidTy () ||
216- (RetTy == I.getType () && shouldReplaceNonVoidReturnValue (BB, &I))) &&
217- canReplaceFuncUsers (F, I.getType ()) && !O.shouldKeep ()) {
220+ if (shouldForwardValueToReturn (BB, &I, RetTy) && !O.shouldKeep ()) {
218221 FuncsToReplace.emplace_back (&F, &I);
219222 return true ;
220223 }
@@ -224,23 +227,24 @@ static bool tryForwardingValuesToReturn(
224227 return false ;
225228}
226229
227- static void reduceValuesToReturn (Oracle &O, ReducerWorkItem &WorkItem) {
230+ // TODO: Add another pass to forward arguments to return values
231+ static void reduceInstructionsToReturn (Oracle &O, ReducerWorkItem &WorkItem) {
228232 Module &Program = WorkItem.getModule ();
229233
230234 // We're going to chaotically hack on the other users of the function in other
231235 // functions, so we need to collect a worklist of returns to replace.
232- std::vector<std::pair<Function *, Instruction *>> FuncsToReplace;
236+ std::vector<std::pair<Function *, Value *>> FuncsToReplace;
233237
234238 for (Function &F : Program.functions ()) {
235239 if (!F.isDeclaration () && canUseNonVoidReturnType (F))
236- tryForwardingValuesToReturn (F, O, FuncsToReplace);
240+ tryForwardingInstructionsToReturn (F, O, FuncsToReplace);
237241 }
238242
239- for (auto [F, I ] : FuncsToReplace)
240- rewriteFuncWithReturnType (*F, I );
243+ for (auto [F, NewRetVal ] : FuncsToReplace)
244+ rewriteFuncWithReturnType (*F, NewRetVal );
241245}
242246
243247void llvm::reduceValuesToReturnDeltaPass (TestRunner &Test) {
244- runDeltaPass (Test, reduceValuesToReturn ,
245- " Converting values to function return value" );
248+ runDeltaPass (Test, reduceInstructionsToReturn ,
249+ " Converting instructions to function return value" );
246250}
0 commit comments