The alignment of an sret parameter is known: it must be at least the

alignment of the return type.  Teach the optimizers this.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@165226 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Duncan Sands 2012-10-04 13:36:31 +00:00
parent e660fc15fe
commit ffcf6dffee
3 changed files with 33 additions and 8 deletions

View File

@ -1107,9 +1107,9 @@ declare signext i8 @returns_signed_char()
<dd>This indicates that the pointer parameter specifies the address of a
structure that is the return value of the function in the source program.
This pointer must be guaranteed by the caller to be valid: loads and
stores to the structure may be assumed by the callee to not to trap. This
may only be applied to the first parameter. This is not a valid attribute
for return values. </dd>
stores to the structure may be assumed by the callee to not to trap and
to be properly aligned. This may only be applied to the first parameter.
This is not a valid attribute for return values. </dd>
<dt><tt><b><a name="noalias">noalias</a></b></tt></dt>
<dd>This indicates that pointer values

View File

@ -308,11 +308,20 @@ void llvm::ComputeMaskedBits(Value *V, APInt &KnownZero, APInt &KnownOne,
}
if (Argument *A = dyn_cast<Argument>(V)) {
// Get alignment information off byval arguments if specified in the IR.
if (A->hasByValAttr())
if (unsigned Align = A->getParamAlignment())
KnownZero = APInt::getLowBitsSet(BitWidth,
CountTrailingZeros_32(Align));
unsigned Align = 0;
if (A->hasByValAttr()) {
// Get alignment information off byval arguments if specified in the IR.
Align = A->getParamAlignment();
} else if (TD && A->hasStructRetAttr()) {
// An sret parameter has at least the ABI alignment of the return type.
Type *EltTy = cast<PointerType>(A->getType())->getElementType();
if (EltTy->isSized())
Align = TD->getABITypeAlignment(EltTy);
}
if (Align)
KnownZero = APInt::getLowBitsSet(BitWidth, CountTrailingZeros_32(Align));
return;
}

View File

@ -58,3 +58,19 @@ define double @test2(double* %p, double %n) nounwind {
store double %n, double* %p
ret double %t
}
declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind
declare void @use(i8*)
%struct.s = type { i32, i32, i32, i32 }
define void @test3(%struct.s* sret %a4) {
; Check that the alignment is bumped up the alignment of the sret type.
; CHECK: @test3
%a4.cast = bitcast %struct.s* %a4 to i8*
call void @llvm.memset.p0i8.i64(i8* %a4.cast, i8 0, i64 16, i32 1, i1 false)
; CHECK: call void @llvm.memset.p0i8.i64(i8* %a4.cast, i8 0, i64 16, i32 4, i1 false)
call void @use(i8* %a4.cast)
ret void
}