Revert r237385, "[CodeGen] Reuse stack space from unused function results"

It broke clang stage2, at least tblgen.

llvm-svn: 237418
This commit is contained in:
NAKAMURA Takumi 2015-05-15 03:49:05 +00:00
parent 95a2a7e612
commit 1a6756bba0
2 changed files with 3 additions and 145 deletions

View File

@ -3077,18 +3077,10 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// If the call returns a temporary with struct return, create a temporary // If the call returns a temporary with struct return, create a temporary
// alloca to hold the result, unless one is given to us. // alloca to hold the result, unless one is given to us.
llvm::Value *SRetPtr = nullptr; llvm::Value *SRetPtr = nullptr;
size_t UnusedReturnSize = 0;
if (RetAI.isIndirect() || RetAI.isInAlloca()) { if (RetAI.isIndirect() || RetAI.isInAlloca()) {
SRetPtr = ReturnValue.getValue(); SRetPtr = ReturnValue.getValue();
if (!SRetPtr) { if (!SRetPtr)
SRetPtr = CreateMemTemp(RetTy); SRetPtr = CreateMemTemp(RetTy);
if (HaveInsertPoint()) {
uint64_t size =
CGM.getDataLayout().getTypeAllocSize(ConvertTypeForMem(RetTy));
if (EmitLifetimeStart(size, SRetPtr))
UnusedReturnSize = size;
}
}
if (IRFunctionArgs.hasSRetArg()) { if (IRFunctionArgs.hasSRetArg()) {
IRCallArgs[IRFunctionArgs.getSRetArgNo()] = SRetPtr; IRCallArgs[IRFunctionArgs.getSRetArgNo()] = SRetPtr;
} else { } else {
@ -3420,10 +3412,6 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// insertion point; this allows the rest of IRgen to discard // insertion point; this allows the rest of IRgen to discard
// unreachable code. // unreachable code.
if (CS.doesNotReturn()) { if (CS.doesNotReturn()) {
if (UnusedReturnSize)
EmitLifetimeEnd(llvm::ConstantInt::get(Int64Ty, UnusedReturnSize),
SRetPtr);
Builder.CreateUnreachable(); Builder.CreateUnreachable();
Builder.ClearInsertionPoint(); Builder.ClearInsertionPoint();
@ -3452,13 +3440,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
RValue Ret = [&] { RValue Ret = [&] {
switch (RetAI.getKind()) { switch (RetAI.getKind()) {
case ABIArgInfo::InAlloca: case ABIArgInfo::InAlloca:
case ABIArgInfo::Indirect: { case ABIArgInfo::Indirect:
RValue ret = convertTempToRValue(SRetPtr, RetTy, SourceLocation()); return convertTempToRValue(SRetPtr, RetTy, SourceLocation());
if (UnusedReturnSize)
EmitLifetimeEnd(llvm::ConstantInt::get(Int64Ty, UnusedReturnSize),
SRetPtr);
return ret;
}
case ABIArgInfo::Ignore: case ABIArgInfo::Ignore:
// If we are ignoring an argument that had a result, make sure to // If we are ignoring an argument that had a result, make sure to

View File

@ -1,125 +0,0 @@
// 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);
}
}
}