diff options
author | Chris Lattner <sabre@nondot.org> | 2010-07-29 18:39:32 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2010-07-29 18:39:32 +0000 |
commit | 0b3620066bfbb33004bed1816c851a923b9301af (patch) | |
tree | c0f57276865ece101a6b70796b26ecf0d2fc3bba /lib | |
parent | cba8d310163f84630fd140fbfa9b6fdad9d26587 (diff) |
Implement the clang-side of detection for when to pass as
<2 x float> instead of double. This works but can't be turned
on until I teach codegen to pass <2 x float> as one XMM register
instead of two.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@109790 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/CodeGen/TargetInfo.cpp | 42 |
1 files changed, 39 insertions, 3 deletions
diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index 6ce824ba18..5f4efcf0bd 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/lib/CodeGen/TargetInfo.cpp @@ -1297,6 +1297,35 @@ static bool BitsContainNoUserData(QualType Ty, unsigned StartBit, return false; } +/// ContainsFloatAtOffset - Return true if the specified LLVM IR type has a +/// float member at the specified offset. For example, {int,{float}} has a +/// float at offset 4. It is conservatively correct for this routine to return +/// false. +static bool ContainsFloatAtOffset(const llvm::Type *IRType, unsigned IROffset, + const llvm::TargetData &TD) { + // Base case if we find a float. + if (IROffset == 0 && IRType->isFloatTy()) + return true; + + // If this is a struct, recurse into the field at the specified offset. + if (const llvm::StructType *STy = dyn_cast<llvm::StructType>(IRType)) { + const llvm::StructLayout *SL = TD.getStructLayout(STy); + unsigned Elt = SL->getElementContainingOffset(IROffset); + IROffset -= SL->getElementOffset(Elt); + return ContainsFloatAtOffset(STy->getElementType(Elt), IROffset, TD); + } + + // If this is an array, recurse into the field at the specified offset. + if (const llvm::ArrayType *ATy = dyn_cast<llvm::ArrayType>(IRType)) { + const llvm::Type *EltTy = ATy->getElementType(); + unsigned EltSize = TD.getTypeAllocSize(EltTy); + IROffset -= IROffset/EltSize*EltSize; + return ContainsFloatAtOffset(EltTy, IROffset, TD); + } + + return false; +} + /// GetSSETypeAtOffset - Return a type that will be passed by the backend in the /// low 8 bytes of an XMM register, corresponding to the SSE class. @@ -1310,9 +1339,16 @@ GetSSETypeAtOffset(const llvm::Type *IRType, unsigned IROffset, SourceOffset*8+64, getContext())) return llvm::Type::getFloatTy(getVMContext()); - // FIXME: <2 x float> doesn't pass as one XMM register yet. Don't enable this - // code until it does. - //return llvm::VectorType::get(llvm::Type::getFloatTy(getVMContext()), 2); + // We want to pass as <2 x float> if the LLVM IR type contains a float at + // offset+0 and offset+4. Walk the LLVM IR type to find out if this is the + // case. + if (ContainsFloatAtOffset(IRType, IROffset, getTargetData()) && + ContainsFloatAtOffset(IRType, IROffset+4, getTargetData())) { + // FIXME: <2 x float> doesn't pass as one XMM register yet. Don't enable + // this code until it does. + //return llvm::VectorType::get(llvm::Type::getFloatTy(getVMContext()), 2); + + } return llvm::Type::getDoubleTy(getVMContext()); } |