diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2011-05-17 21:08:01 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2011-05-17 21:08:01 +0000 |
commit | af9b325d232f52ca858c67cd497b79f5e63716af (patch) | |
tree | 9cb0d9a100ef9dbbba860c66830693139fab6296 /clang | |
parent | 3597b6340c00dd2bf720b0f66c43b5698e2d04b6 (diff) | |
download | bcm5719-llvm-af9b325d232f52ca858c67cd497b79f5e63716af.tar.gz bcm5719-llvm-af9b325d232f52ca858c67cd497b79f5e63716af.zip |
For calls returning first-class aggregates, store by element instead of creating aggregate stores in common cases. This is more friendly to fast-isel.
llvm-svn: 131490
Diffstat (limited to 'clang')
-rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 27 | ||||
-rw-r--r-- | clang/test/CodeGenObjCXX/property-object-conditional-exp.mm | 7 |
2 files changed, 31 insertions, 3 deletions
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 6b6f3176b02..fba89a76fc6 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -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); diff --git a/clang/test/CodeGenObjCXX/property-object-conditional-exp.mm b/clang/test/CodeGenObjCXX/property-object-conditional-exp.mm index 826c351e79e..a3c1027ed70 100644 --- a/clang/test/CodeGenObjCXX/property-object-conditional-exp.mm +++ b/clang/test/CodeGenObjCXX/property-object-conditional-exp.mm @@ -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; |