[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