[cfe-commits] r166040 - in /cfe/trunk: lib/CodeGen/TargetInfo.cpp test/CodeGen/arm-abi-vector.c
Eli Friedman
eli.friedman at gmail.com
Tue Oct 16 13:32:10 PDT 2012
On Tue, Oct 16, 2012 at 12:01 PM, Manman Ren <mren at apple.com> wrote:
> Author: mren
> Date: Tue Oct 16 14:01:37 2012
> New Revision: 166040
>
> URL: http://llvm.org/viewvc/llvm-project?rev=166040&view=rev
> Log:
> ARM ABI: fix ABI alignment issues when passing legal vector types as varargs.
>
> We create an aligned temporary space and copy the content over from ap.cur to
> the temporary space. This is necessary if the natural alignment of the type is
> greater than the ABI alignment.
>
> rdar://12439123
>
> Added:
> cfe/trunk/test/CodeGen/arm-abi-vector.c
> Modified:
> cfe/trunk/lib/CodeGen/TargetInfo.cpp
>
> Modified: cfe/trunk/lib/CodeGen/TargetInfo.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/TargetInfo.cpp?rev=166040&r1=166039&r2=166040&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/TargetInfo.cpp (original)
> +++ cfe/trunk/lib/CodeGen/TargetInfo.cpp Tue Oct 16 14:01:37 2012
> @@ -3169,27 +3169,59 @@
> CGBuilderTy &Builder = CGF.Builder;
> llvm::Value *VAListAddrAsBPP = Builder.CreateBitCast(VAListAddr, BPP, "ap");
> llvm::Value *Addr = Builder.CreateLoad(VAListAddrAsBPP, "ap.cur");
> - // Handle address alignment for type alignment > 32 bits
> +
> + uint64_t Size = CGF.getContext().getTypeSize(Ty) / 8;
> uint64_t TyAlign = CGF.getContext().getTypeAlign(Ty) / 8;
> +
> + // The ABI alignment for 64-bit or 128-bit vectors is 8 for AAPCS and 4 for
> + // APCS. For AAPCS, the ABI alignment is at least 4-byte and at most 8-byte.
> + if (Ty->getAs<VectorType>()) {
> + if (getABIKind() == ARMABIInfo::AAPCS_VFP ||
> + getABIKind() == ARMABIInfo::AAPCS)
> + TyAlign = std::min(std::max(TyAlign, (uint64_t)4), (uint64_t)8);
> + else
> + TyAlign = 4;
> + }
> +
> + // Handle address alignment for ABI alignment > 4 bytes.
> if (TyAlign > 4) {
> assert((TyAlign & (TyAlign - 1)) == 0 &&
> "Alignment is not power of 2!");
> llvm::Value *AddrAsInt = Builder.CreatePtrToInt(Addr, CGF.Int32Ty);
> AddrAsInt = Builder.CreateAdd(AddrAsInt, Builder.getInt32(TyAlign - 1));
> AddrAsInt = Builder.CreateAnd(AddrAsInt, Builder.getInt32(~(TyAlign - 1)));
> - Addr = Builder.CreateIntToPtr(AddrAsInt, BP);
> + Addr = Builder.CreateIntToPtr(AddrAsInt, BP, "ap.align");
> }
> - llvm::Type *PTy =
> - llvm::PointerType::getUnqual(CGF.ConvertType(Ty));
> - llvm::Value *AddrTyped = Builder.CreateBitCast(Addr, PTy);
>
> uint64_t Offset =
> - llvm::RoundUpToAlignment(CGF.getContext().getTypeSize(Ty) / 8, 4);
> + llvm::RoundUpToAlignment(Size, 4);
> llvm::Value *NextAddr =
> Builder.CreateGEP(Addr, llvm::ConstantInt::get(CGF.Int32Ty, Offset),
> "ap.next");
> Builder.CreateStore(NextAddr, VAListAddrAsBPP);
>
> + if (Ty->getAs<VectorType>() &&
> + (TyAlign < CGF.getContext().getTypeAlign(Ty) / 8)) {
> + // We can't directly cast ap.cur to pointer to a vector type, since ap.cur
> + // may not be correctly aligned for the vector type. We create an aligned
> + // temporary space and copy the content over from ap.cur to the temporary
> + // space. This is necessary if the natural alignment of the type is greater
> + // than the ABI alignment.
> + llvm::Type *I8PtrTy = Builder.getInt8PtrTy();
> + CharUnits CharSize = getContext().getTypeSizeInChars(Ty);
> + llvm::Value *AlignedTemp = CGF.CreateTempAlloca(CGF.ConvertType(Ty),
> + "var.align");
> + llvm::Value *Dst = Builder.CreateBitCast(AlignedTemp, I8PtrTy);
> + llvm::Value *Src = Builder.CreateBitCast(Addr, I8PtrTy);
> + Builder.CreateMemCpy(Dst, Src,
> + llvm::ConstantInt::get(CGF.IntPtrTy, CharSize.getQuantity()),
> + TyAlign, false);
> + Addr = AlignedTemp; //The content is in aligned location.
> + }
> + llvm::Type *PTy =
> + llvm::PointerType::getUnqual(CGF.ConvertType(Ty));
> + llvm::Value *AddrTyped = Builder.CreateBitCast(Addr, PTy);
> +
> return AddrTyped;
> }
>
>
> Added: cfe/trunk/test/CodeGen/arm-abi-vector.c
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/arm-abi-vector.c?rev=166040&view=auto
> ==============================================================================
> --- cfe/trunk/test/CodeGen/arm-abi-vector.c (added)
> +++ cfe/trunk/test/CodeGen/arm-abi-vector.c Tue Oct 16 14:01:37 2012
> @@ -0,0 +1,38 @@
> +// RUN: %clang_cc1 -triple armv7-apple-darwin -target-abi aapcs -emit-llvm -o - %s | FileCheck %s
> +// RUN: %clang_cc1 -triple armv7-apple-darwin -target-abi apcs-gnu -emit-llvm -o - %s | FileCheck -check-prefix=APCS-GNU %s
> +
> +#include <stdarg.h>
> +
> +typedef __attribute__(( ext_vector_type(2) )) int __int2;
> +
> +// Passing legal vector types as varargs.
> +double varargs_vec_2i(int fixed, ...) {
> +// CHECK: varargs_vec_2i
> +// CHECK: %c3 = alloca <2 x i32>, align 8
> +// CHECK: %3 = and i32 %2, -8
> +// CHECK: %ap.align = inttoptr i32 %3 to i8*
> +// CHECK: %ap.next = getelementptr i8* %ap.align, i32 8
> +// CHECK: bitcast i8* %ap.align to <2 x i32>*
> +// APCS-GNU: varargs_vec_2i
> +// APCS-GNU: %c3 = alloca <2 x i32>, align 8
> +// APCS-GNU: %var.align = alloca <2 x i32>
> +// APCS-GNU: %ap.next = getelementptr i8* %ap.cur, i32 8
> +// APCS-GNU: %1 = bitcast <2 x i32>* %var.align to i8*
> +// APCS-GNU: call void @llvm.memcpy
> +// APCS-GNU: %2 = load <2 x i32>* %var.align
You can't use the explicit value names in clang CodeGen tests; we
strip the names in builds with assertions turned off. Use FileCheck
variables like [[VAR]] instead.
Sorry I missed this earlier.
-Eli
More information about the cfe-commits
mailing list