aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen
diff options
context:
space:
mode:
authorChandler Carruth <chandlerc@gmail.com>2012-10-10 11:29:08 +0000
committerChandler Carruth <chandlerc@gmail.com>2012-10-10 11:29:08 +0000
commitf82232c8b73851337b83b954ba1292cf6475c7c5 (patch)
tree82daa1af8c1452d0fed3440f53161da621fb5042 /lib/CodeGen
parent603571a2d6daca43162bf1d9469baf919697c00a (diff)
Apply the same fundamental fix for PR14048 as was applied for PR11905.
The issue arises when coercing to/from types of different sizes. We need to be certain that the allocation on either end has sufficient room for the coerced type. When it doesn't, we need to make room, copy across, and then proceed. PR11905 handled the case of storing function arguments back into allocas in the function prolog, this patch handles the case of setting up the function arguments in a call expression. This is actually significantly simpler than the fix for PR11905. It ends up being a trivial change to create a temporary alloca when the source is too small and memcpy across. This should preserve the compile-time fast-isel benefits of doing gep+load sequences and avoiding FCAs. Reviewed by Benjamin and Evgeniy (who fixed PR11905). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@165615 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/CGCall.cpp21
1 files changed, 19 insertions, 2 deletions
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index 562c17ded3..e8d99e2f5a 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -2073,8 +2073,25 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// and the optimizer generally likes scalar values better than FCAs.
if (llvm::StructType *STy =
dyn_cast<llvm::StructType>(ArgInfo.getCoerceToType())) {
- SrcPtr = Builder.CreateBitCast(SrcPtr,
- llvm::PointerType::getUnqual(STy));
+ llvm::Type *SrcTy =
+ cast<llvm::PointerType>(SrcPtr->getType())->getElementType();
+ uint64_t SrcSize = CGM.getDataLayout().getTypeAllocSize(SrcTy);
+ uint64_t DstSize = CGM.getDataLayout().getTypeAllocSize(STy);
+
+ // If the source type is smaller than the destination type of the
+ // coerce-to logic, copy the source value into a temp alloca the size
+ // of the destination type to allow loading all of it. The bits past
+ // the source value are left undef.
+ if (SrcSize < DstSize) {
+ llvm::AllocaInst *TempAlloca
+ = CreateTempAlloca(STy, SrcPtr->getName() + ".coerce");
+ Builder.CreateMemCpy(TempAlloca, SrcPtr, SrcSize, 0);
+ SrcPtr = TempAlloca;
+ } else {
+ SrcPtr = Builder.CreateBitCast(SrcPtr,
+ llvm::PointerType::getUnqual(STy));
+ }
+
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
llvm::Value *EltPtr = Builder.CreateConstGEP2_32(SrcPtr, 0, i);
llvm::LoadInst *LI = Builder.CreateLoad(EltPtr);