[PATCH] D24523: [ObjCARC] Traverse chain downwards to replace uses of argument passed to ObjC library call with call return
Akira Hatanaka via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 13 17:04:43 PDT 2016
Thanks Pete. Committed in r281419 and r281421.
On Tue, Sep 13, 2016 at 3:29 PM, Pete Cooper <peter_cooper at apple.com> wrote:
> Hi Akira
>
> Just a single nit. Can you please define *OrigArg on its own line as its
> easier to read.
>
> Otherwise LGTM. I’m surprised we didn’t come across this issue sooner!
>
> Cheers,
> Pete
> > On Sep 13, 2016, at 2:55 PM, Akira Hatanaka <ahatanak at gmail.com> wrote:
> >
> > ahatanak created this revision.
> > ahatanak added reviewers: gottesmm, pete, rjmccall.
> > ahatanak added a subscriber: llvm-commits.
> >
> > ObjCARCContract::runOnFunction tries to replace uses of an argument
> passed to an objective-c library call with the call
> > return value. For example, in the following IR, it replaces uses of
> argument %9 and uses of the values discovered traversing the chain upwards
> (%7 and %8) with the call return %10, if they are dominated by the call to
> @objc_autoreleaseReturnValue. This transformation enables code-gen to
> tail-call the call to @objc_autoreleaseReturnValue, which is necessary to
> enable auto release return value optimization.
> >
> > ```
> > %7 = tail call i8* @objc_loadWeakRetained(i8** %6)
> > %8 = bitcast i8* %7 to %0*
> > %9 = bitcast %0* %8 to i8*
> > %10 = tail call i8* @objc_autoreleaseReturnValue(i8* %9)
> > ret %0* %8
> > ```
> >
> > Since r276727, llvm started removing redundant bitcasts and as a result
> started feeding the following IR to ARC contraction:
> >
> > ```
> > %7 = tail call i8* @objc_loadWeakRetained(i8** %6)
> > %8 = bitcast i8* %7 to %0*
> > %9 = tail call i8* @objc_autoreleaseReturnValue(i8* %7)
> > ret %0* %8
> > ```
> >
> > ARC contraction no longer does the optimization described above since it
> only traverses the chain upwards and fails to recognize that the function
> return can be replaced by the call return from
> @objc_autoreleaseReturnValue. This patch changes
> ObjCARCContract::runOnFunction to traverse the chain downwards too and
> replace uses of bitcasts with the call return.
> >
> > rdar://problem/28011339
> >
> > https://reviews.llvm.org/D24523
> >
> > Files:
> > lib/Transforms/ObjCARC/ObjCARCContract.cpp
> > test/Transforms/ObjCARC/contract-replace-arg-use.ll
> >
> > Index: test/Transforms/ObjCARC/contract-replace-arg-use.ll
> > ===================================================================
> > --- /dev/null
> > +++ test/Transforms/ObjCARC/contract-replace-arg-use.ll
> > @@ -0,0 +1,18 @@
> > +; RUN: opt -objc-arc-contract -S < %s | FileCheck %s
> > +
> > +declare i8* @objc_autoreleaseReturnValue(i8*)
> > +declare i8* @foo1()
> > +
> > +; Check that ARC contraction replaces the function return with the value
> > +; returned by @objc_autoreleaseReturnValue.
> > +
> > +; CHECK: %[[V0:[0-9]+]] = tail call i8* @objc_autoreleaseReturnValue(
> > +; CHECK: %[[V1:[0-9]+]] = bitcast i8* %[[V0]] to i32*
> > +; CHECK: ret i32* %[[V1]]
> > +
> > +define i32* @autoreleaseRVTailCall() {
> > + %1 = call i8* @foo1()
> > + %2 = bitcast i8* %1 to i32*
> > + %3 = tail call i8* @objc_autoreleaseReturnValue(i8* %1)
> > + ret i32* %2
> > +}
> > Index: lib/Transforms/ObjCARC/ObjCARCContract.cpp
> > ===================================================================
> > --- lib/Transforms/ObjCARC/ObjCARCContract.cpp
> > +++ lib/Transforms/ObjCARC/ObjCARCContract.cpp
> > @@ -547,13 +547,13 @@
> >
> > // 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 @@
> > }
> > }
> > }
> > + };
> > +
> > +
> > + 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 @@
> > 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,
> >
> >
> > <D24523.71239.patch>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160913/62bb145d/attachment-0001.html>
More information about the llvm-commits
mailing list