r237385 - [CodeGen] Reuse stack space from unused function results

NAKAMURA Takumi geek4civic at gmail.com
Fri May 15 06:32:11 PDT 2015


Sergey, excuse me, I reverted it in r237418.
It miscompiled *-tblgen to crash.

File attached. In bad.ll,

  %lt.tmp12 = bitcast %"class.llvm::Twine"* %tmp to i8*
...
  call void @llvm.lifetime.start(i64 24, i8* %lt.tmp12) #1
  call void @_ZN4llvmplERKNS_5TwineES2_(%"class.llvm::Twine"* sret
%tmp, %"class.llvm::Twine"* dereferenceable(24) %ref.tmp28,
%"class.llvm::Twine"* dereferenceable(24) %ref.tmp29)
  call void @llvm.lifetime.end(i64 24, i8* %lt.tmp12) #1

It works if both @llvm.lifetime.start and @llvm.lifetime.end are pruned.

...Takumi

2015-05-15 4:58 GMT+09:00 Sergey Dmitrouk <sdmitrouk at accesssoftek.com>:
> Author: sdmitrouk
> Date: Thu May 14 14:58:03 2015
> New Revision: 237385
>
> URL: http://llvm.org/viewvc/llvm-project?rev=237385&view=rev
> Log:
> [CodeGen] Reuse stack space from unused function results
>
> Summary:
> Space on stack allocated for unused structures returned by functions was unused
> even when it's lifetime didn't intersect with lifetime of any other objects that
> could use the same space.
>
> The test added also checks for named and auto objects.  It seems to make sense
> to have this all in one place.
>
> Reviewers: aadg, rsmith, rjmccall, rnk
>
> Reviewed By: rnk
>
> Subscribers: asl, cfe-commits
>
> Differential Revision: http://reviews.llvm.org/D9743
>
> Added:
>     cfe/trunk/test/CodeGenCXX/stack-reuse.cpp
> Modified:
>     cfe/trunk/lib/CodeGen/CGCall.cpp
>
> Modified: cfe/trunk/lib/CodeGen/CGCall.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=237385&r1=237384&r2=237385&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGCall.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGCall.cpp Thu May 14 14:58:03 2015
> @@ -3077,10 +3077,18 @@ RValue CodeGenFunction::EmitCall(const C
>    // If the call returns a temporary with struct return, create a temporary
>    // alloca to hold the result, unless one is given to us.
>    llvm::Value *SRetPtr = nullptr;
> +  size_t UnusedReturnSize = 0;
>    if (RetAI.isIndirect() || RetAI.isInAlloca()) {
>      SRetPtr = ReturnValue.getValue();
> -    if (!SRetPtr)
> +    if (!SRetPtr) {
>        SRetPtr = CreateMemTemp(RetTy);
> +      if (HaveInsertPoint()) {
> +        uint64_t size =
> +            CGM.getDataLayout().getTypeAllocSize(ConvertTypeForMem(RetTy));
> +        if (EmitLifetimeStart(size, SRetPtr))
> +          UnusedReturnSize = size;
> +      }
> +    }
>      if (IRFunctionArgs.hasSRetArg()) {
>        IRCallArgs[IRFunctionArgs.getSRetArgNo()] = SRetPtr;
>      } else {
> @@ -3412,6 +3420,10 @@ RValue CodeGenFunction::EmitCall(const C
>    // insertion point; this allows the rest of IRgen to discard
>    // unreachable code.
>    if (CS.doesNotReturn()) {
> +    if (UnusedReturnSize)
> +      EmitLifetimeEnd(llvm::ConstantInt::get(Int64Ty, UnusedReturnSize),
> +                      SRetPtr);
> +
>      Builder.CreateUnreachable();
>      Builder.ClearInsertionPoint();
>
> @@ -3440,8 +3452,13 @@ RValue CodeGenFunction::EmitCall(const C
>    RValue Ret = [&] {
>      switch (RetAI.getKind()) {
>      case ABIArgInfo::InAlloca:
> -    case ABIArgInfo::Indirect:
> -      return convertTempToRValue(SRetPtr, RetTy, SourceLocation());
> +    case ABIArgInfo::Indirect: {
> +      RValue ret = convertTempToRValue(SRetPtr, RetTy, SourceLocation());
> +      if (UnusedReturnSize)
> +        EmitLifetimeEnd(llvm::ConstantInt::get(Int64Ty, UnusedReturnSize),
> +                        SRetPtr);
> +      return ret;
> +    }
>
>      case ABIArgInfo::Ignore:
>        // If we are ignoring an argument that had a result, make sure to
>
> Added: cfe/trunk/test/CodeGenCXX/stack-reuse.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/stack-reuse.cpp?rev=237385&view=auto
> ==============================================================================
> --- cfe/trunk/test/CodeGenCXX/stack-reuse.cpp (added)
> +++ cfe/trunk/test/CodeGenCXX/stack-reuse.cpp Thu May 14 14:58:03 2015
> @@ -0,0 +1,125 @@
> +// RUN: %clang -target armv7l-unknown-linux-gnueabihf -S %s -o - -emit-llvm -O1 -disable-llvm-optzns | FileCheck %s
> +
> +// Stack should be reused when possible, no need to allocate two separate slots
> +// if they have disjoint lifetime.
> +
> +// Sizes of objects are related to previously existed threshold of 32.  In case
> +// of S_large stack size is rounded to 40 bytes.
> +
> +// 32B
> +struct S_small {
> +  int a[8];
> +};
> +
> +// 36B
> +struct S_large {
> +  int a[9];
> +};
> +
> +extern S_small foo_small();
> +extern S_large foo_large();
> +extern void bar_small(S_small*);
> +extern void bar_large(S_large*);
> +
> +// Prevent mangling of function names.
> +extern "C" {
> +
> +void small_rvoed_unnamed_temporary_object() {
> +// CHECK-LABEL: define void @small_rvoed_unnamed_temporary_object
> +// CHECK: call void @llvm.lifetime.start
> +// CHECK: call void @_Z9foo_smallv
> +// CHECK: call void @llvm.lifetime.end
> +// CHECK: call void @llvm.lifetime.start
> +// CHECK: call void @_Z9foo_smallv
> +// CHECK: call void @llvm.lifetime.end
> +
> +  foo_small();
> +  foo_small();
> +}
> +
> +void large_rvoed_unnamed_temporary_object() {
> +// CHECK-LABEL: define void @large_rvoed_unnamed_temporary_object
> +// CHECK: call void @llvm.lifetime.start
> +// CHECK: call void @_Z9foo_largev
> +// CHECK: call void @llvm.lifetime.end
> +// CHECK: call void @llvm.lifetime.start
> +// CHECK: call void @_Z9foo_largev
> +// CHECK: call void @llvm.lifetime.end
> +
> +  foo_large();
> +  foo_large();
> +}
> +
> +void small_rvoed_named_temporary_object() {
> +// CHECK-LABEL: define void @small_rvoed_named_temporary_object
> +// CHECK: call void @llvm.lifetime.start
> +// CHECK: call void @_Z9foo_smallv
> +// CHECK: call void @llvm.lifetime.end
> +// CHECK: call void @llvm.lifetime.start
> +// CHECK: call void @_Z9foo_smallv
> +// CHECK: call void @llvm.lifetime.end
> +
> +  {
> +    S_small s = foo_small();
> +  }
> +  {
> +    S_small s = foo_small();
> +  }
> +}
> +
> +void large_rvoed_named_temporary_object() {
> +// CHECK-LABEL: define void @large_rvoed_named_temporary_object
> +// CHECK: call void @llvm.lifetime.start
> +// CHECK: call void @_Z9foo_largev
> +// CHECK: call void @llvm.lifetime.end
> +// CHECK: call void @llvm.lifetime.start
> +// CHECK: call void @_Z9foo_largev
> +// CHECK: call void @llvm.lifetime.end
> +
> +  {
> +    S_large s = foo_large();
> +  }
> +  {
> +    S_large s = foo_large();
> +  }
> +}
> +
> +void small_auto_object() {
> +// CHECK-LABEL: define void @small_auto_object
> +// CHECK: call void @llvm.lifetime.start
> +// CHECK: call void @_Z9bar_smallP7S_small
> +// CHECK: call void @llvm.lifetime.end
> +// CHECK: call void @llvm.lifetime.start
> +// CHECK: call void @_Z9bar_smallP7S_small
> +// CHECK: call void @llvm.lifetime.end
> +
> +  {
> +    S_small s;
> +    bar_small(&s);
> +  }
> +  {
> +    S_small s;
> +    bar_small(&s);
> +  }
> +}
> +
> +void large_auto_object() {
> +// CHECK-LABEL: define void @large_auto_object
> +// CHECK: call void @llvm.lifetime.start
> +// CHECK: call void @_Z9bar_largeP7S_large
> +// CHECK: call void @llvm.lifetime.end
> +// CHECK: call void @llvm.lifetime.start
> +// CHECK: call void @_Z9bar_largeP7S_large
> +// CHECK: call void @llvm.lifetime.end
> +
> +  {
> +    S_large s;
> +    bar_large(&s);
> +  }
> +  {
> +    S_large s;
> +    bar_large(&s);
> +  }
> +}
> +
> +}
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
-------------- next part --------------
A non-text attachment was scrubbed...
Name: r237385.zip
Type: application/zip
Size: 96539 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20150515/9239f950/attachment.zip>


More information about the cfe-commits mailing list