]> granicus.if.org Git - clang/commitdiff
For calls returning first-class aggregates, store by element instead of creating...
authorEli Friedman <eli.friedman@gmail.com>
Tue, 17 May 2011 21:08:01 +0000 (21:08 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Tue, 17 May 2011 21:08:01 +0000 (21:08 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@131490 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGCall.cpp
test/CodeGenObjCXX/property-object-conditional-exp.mm

index 6b6f3176b029b33219750398db91a50f08c5f10e..fba89a76fc65df9482f1a020c3a7cc128a672dad 100644 (file)
@@ -513,6 +513,29 @@ static llvm::Value *CreateCoercedLoad(llvm::Value *SrcPtr,
   return CGF.Builder.CreateLoad(Tmp);
 }
 
+// Function to store a first-class aggregate into memory.  We prefer to
+// store the elements rather than the aggregate to be more friendly to
+// fast-isel.
+// FIXME: Do we need to recurse here?
+static void BuildAggStore(CodeGenFunction &CGF, llvm::Value *Val,
+                          llvm::Value *DestPtr, bool DestIsVolatile,
+                          bool LowAlignment) {
+  // Prefer scalar stores to first-class aggregate stores.
+  if (const llvm::StructType *STy =
+        dyn_cast<llvm::StructType>(Val->getType())) {
+    for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
+      llvm::Value *EltPtr = CGF.Builder.CreateConstGEP2_32(DestPtr, 0, i);
+      llvm::Value *Elt = CGF.Builder.CreateExtractValue(Val, i);
+      llvm::StoreInst *SI = CGF.Builder.CreateStore(Elt, EltPtr,
+                                                    DestIsVolatile);
+      if (LowAlignment)
+        SI->setAlignment(1);
+    }
+  } else {
+    CGF.Builder.CreateStore(Val, DestPtr, DestIsVolatile);
+  }
+}
+
 /// CreateCoercedStore - Create a store to \arg DstPtr from \arg Src,
 /// where the source and destination may have different types.
 ///
@@ -553,7 +576,7 @@ static void CreateCoercedStore(llvm::Value *Src,
     llvm::Value *Casted =
       CGF.Builder.CreateBitCast(DstPtr, llvm::PointerType::getUnqual(SrcTy));
     // FIXME: Use better alignment / avoid requiring aligned store.
-    CGF.Builder.CreateStore(Src, Casted, DstIsVolatile)->setAlignment(1);
+    BuildAggStore(CGF, Src, Casted, DstIsVolatile, true);
   } else {
     // Otherwise do coercion through memory. This is stupid, but
     // simple.
@@ -1409,7 +1432,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
           DestPtr = CreateMemTemp(RetTy, "agg.tmp");
           DestIsVolatile = false;
         }
-        Builder.CreateStore(CI, DestPtr, DestIsVolatile);
+        BuildAggStore(*this, CI, DestPtr, DestIsVolatile, false);
         return RValue::getAggregate(DestPtr);
       }
       return RValue::get(CI);
index 826c351e79efa90e59d508227ee3ec7e8a2448f8..a3c1027ed709d04a97a4bb7de0533021ceab6bcf 100644 (file)
@@ -23,7 +23,12 @@ extern "C" bool CGRectIsEmpty(CGRect);
     CGRect virtualBounds;
 
 // CHECK: [[SRC:%.*]] = call %struct.CGRect bitcast (i8* (i8*, i8*, ...)* @objc_msgSend
-// CHECK-NEXT:store %struct.CGRect [[SRC]], %struct.CGRect*
+// CHECK-NEXT:getelementptr %struct.CGRect* [[SRC:%.*]]
+// CHECK-NEXT:extractvalue
+// CHECK-NEXT:store
+// CHECK-NEXT:getelementptr %struct.CGRect* [[SRC:%.*]]
+// CHECK-NEXT:extractvalue
+// CHECK-NEXT:store
   dataRect = CGRectIsEmpty(virtualBounds) ? self.bounds : virtualBounds;
   dataRect = CGRectIsEmpty(virtualBounds) ? [self bounds] : virtualBounds;
   dataRect = CGRectIsEmpty(virtualBounds) ? virtualBounds : self.bounds;