[llvm-commits] [llvm-gcc-4.2] r90914 - /llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp

Stuart Hastings stuart at apple.com
Tue Dec 8 16:55:57 PST 2009


Author: stuart
Date: Tue Dec  8 18:55:56 2009
New Revision: 90914

URL: http://llvm.org/viewvc/llvm-project?rev=90914&view=rev
Log:
If a callee returns a structure in registers, but the stored image of
those registers is bigger than the destination, store the registers
into a temporary, and copy the desired (smaller) part to the
destination.  <rdar://problem/7437022>
The original testcase returned an array of three 32-bit floats,
wrapped in a struct; the value was returned as two doubles in xmm0/1,
and stored as a 128-bit value.

Modified:
    llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp

Modified: llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp?rev=90914&r1=90913&r2=90914&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp Tue Dec  8 18:55:56 2009
@@ -2776,8 +2776,26 @@
     return 0;
 
   if (Client.isAggrReturn()) {
-    Value *Dest = BitCastToType(DestLoc->Ptr, Call->getType()->getPointerTo());
-    LLVM_EXTRACT_MULTIPLE_RETURN_VALUE(Call,Dest,DestLoc->Volatile,Builder);
+    if (TD.getTypeAllocSize(Call->getType()) <= TD.getTypeAllocSize(DestLoc->Ptr->getType())) {
+      Value *Dest = BitCastToType(DestLoc->Ptr, Call->getType()->getPointerTo());
+      LLVM_EXTRACT_MULTIPLE_RETURN_VALUE(Call,Dest,DestLoc->Volatile,Builder);
+    } else {
+      // The call will return an aggregate value in registers, but
+      // those registers are bigger than DestLoc.  Allocate a
+      // temporary to match the registers, store the registers there,
+      // cast the temporary into the correct (smaller) type, and using
+      // the correct type, copy the value into DestLoc.  Assume the
+      // optimizer will delete the temporary and clean this up.
+      AllocaInst *biggerTmp = CreateTemporary(Call->getType());
+      LLVM_EXTRACT_MULTIPLE_RETURN_VALUE(Call,biggerTmp,/*Volatile=*/false,
+					 Builder);
+      EmitAggregateCopy(*DestLoc,
+			MemRef(BitCastToType(biggerTmp,Call->getType()->
+					     getPointerTo()),
+			       DestLoc->getAlignment(),
+			       DestLoc->Volatile),
+			TREE_TYPE(exp));
+    }
     return 0;
   }
 





More information about the llvm-commits mailing list