diff options
Diffstat (limited to 'llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp')
-rw-r--r-- | llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp | 34 |
1 files changed, 30 insertions, 4 deletions
diff --git a/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp b/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp index 4e27793f3e9..c2cc236493b 100644 --- a/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp +++ b/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp @@ -547,13 +547,13 @@ bool ObjCARCContract::runOnFunction(Function &F) { // Don't use GetArgRCIdentityRoot because we don't want to look through bitcasts // and such; to do the replacement, the argument must have type i8*. - Value *Arg = cast<CallInst>(Inst)->getArgOperand(0); - // TODO: Change this to a do-while. - for (;;) { + // Function for replacing uses of Arg dominated by Inst. + auto ReplaceArgUses = [Inst, this](Value *Arg) { // If we're compiling bugpointed code, don't get in trouble. if (!isa<Instruction>(Arg) && !isa<Argument>(Arg)) - break; + return; + // Look through the uses of the pointer. for (Value::use_iterator UI = Arg->use_begin(), UE = Arg->use_end(); UI != UE; ) { @@ -598,6 +598,14 @@ bool ObjCARCContract::runOnFunction(Function &F) { } } } + }; + + + Value *Arg = cast<CallInst>(Inst)->getArgOperand(0), *OrigArg = Arg; + + // TODO: Change this to a do-while. + for (;;) { + ReplaceArgUses(Arg); // If Arg is a no-op casted pointer, strip one level of casts and iterate. if (const BitCastInst *BI = dyn_cast<BitCastInst>(Arg)) @@ -611,6 +619,24 @@ bool ObjCARCContract::runOnFunction(Function &F) { else break; } + + // Replace bitcast users of Arg that are dominated by Inst. + SmallVector<BitCastInst *, 2> BitCastUsers; + + // Add all bitcast users of the function argument first. + for (User *U : OrigArg->users()) + if (auto *BC = dyn_cast<BitCastInst>(U)) + BitCastUsers.push_back(BC); + + // Replace the bitcasts with the call return. Iterate until list is empty. + while (!BitCastUsers.empty()) { + auto *BC = BitCastUsers.pop_back_val(); + for (User *U : BC->users()) + if (auto *B = dyn_cast<BitCastInst>(U)) + BitCastUsers.push_back(B); + + ReplaceArgUses(BC); + } } // If this function has no escaping allocas or suspicious vararg usage, |