diff options
-rw-r--r-- | docs/LangRef.html | 6 | ||||
-rw-r--r-- | lib/Analysis/ValueTracking.cpp | 19 | ||||
-rw-r--r-- | test/Transforms/InstCombine/align-addr.ll | 16 |
3 files changed, 33 insertions, 8 deletions
diff --git a/docs/LangRef.html b/docs/LangRef.html index 89b9227b72..7ee1418f31 100644 --- a/docs/LangRef.html +++ b/docs/LangRef.html @@ -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 diff --git a/lib/Analysis/ValueTracking.cpp b/lib/Analysis/ValueTracking.cpp index 491224a4b6..1004ebcac2 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<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; } diff --git a/test/Transforms/InstCombine/align-addr.ll b/test/Transforms/InstCombine/align-addr.ll index 27916b9860..4ea1bd9beb 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 +} |