From: Duncan Sands Date: Thu, 4 Oct 2012 13:36:31 +0000 (+0000) Subject: The alignment of an sret parameter is known: it must be at least the X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=ffcf6dffee69bd586ab8aa3e24ebbca1d5d279e7;p=oota-llvm.git 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 --- diff --git a/docs/LangRef.html b/docs/LangRef.html index 89b9227b722..7ee1418f316 100644 --- a/docs/LangRef.html +++ b/docs/LangRef.html @@ -1107,9 +1107,9 @@ declare signext i8 @returns_signed_char()
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.
+ 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.
noalias
This indicates that pointer values diff --git a/lib/Analysis/ValueTracking.cpp b/lib/Analysis/ValueTracking.cpp index 491224a4b69..1004ebcac2f 100644 --- a/lib/Analysis/ValueTracking.cpp +++ b/lib/Analysis/ValueTracking.cpp @@ -308,11 +308,20 @@ void llvm::ComputeMaskedBits(Value *V, APInt &KnownZero, APInt &KnownOne, } if (Argument *A = dyn_cast(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(A->getType())->getElementType(); + if (EltTy->isSized()) + Align = TD->getABITypeAlignment(EltTy); + } + + if (Align) + KnownZero = APInt::getLowBitsSet(BitWidth, CountTrailingZeros_32(Align)); return; } diff --git a/test/Transforms/InstCombine/align-addr.ll b/test/Transforms/InstCombine/align-addr.ll index 27916b98603..4ea1bd9beb3 100644 --- a/test/Transforms/InstCombine/align-addr.ll +++ b/test/Transforms/InstCombine/align-addr.ll @@ -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 +}