зеркало из https://github.com/microsoft/clang.git
For calls returning first-class aggregates, store by element instead of creating aggregate stores in common cases. This is more friendly to fast-isel.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@131490 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
492bafc66b
Коммит
badea57d1d
|
@ -513,6 +513,29 @@ static llvm::Value *CreateCoercedLoad(llvm::Value *SrcPtr,
|
||||||
return CGF.Builder.CreateLoad(Tmp);
|
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,
|
/// CreateCoercedStore - Create a store to \arg DstPtr from \arg Src,
|
||||||
/// where the source and destination may have different types.
|
/// where the source and destination may have different types.
|
||||||
///
|
///
|
||||||
|
@ -553,7 +576,7 @@ static void CreateCoercedStore(llvm::Value *Src,
|
||||||
llvm::Value *Casted =
|
llvm::Value *Casted =
|
||||||
CGF.Builder.CreateBitCast(DstPtr, llvm::PointerType::getUnqual(SrcTy));
|
CGF.Builder.CreateBitCast(DstPtr, llvm::PointerType::getUnqual(SrcTy));
|
||||||
// FIXME: Use better alignment / avoid requiring aligned store.
|
// FIXME: Use better alignment / avoid requiring aligned store.
|
||||||
CGF.Builder.CreateStore(Src, Casted, DstIsVolatile)->setAlignment(1);
|
BuildAggStore(CGF, Src, Casted, DstIsVolatile, true);
|
||||||
} else {
|
} else {
|
||||||
// Otherwise do coercion through memory. This is stupid, but
|
// Otherwise do coercion through memory. This is stupid, but
|
||||||
// simple.
|
// simple.
|
||||||
|
@ -1409,7 +1432,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
|
||||||
DestPtr = CreateMemTemp(RetTy, "agg.tmp");
|
DestPtr = CreateMemTemp(RetTy, "agg.tmp");
|
||||||
DestIsVolatile = false;
|
DestIsVolatile = false;
|
||||||
}
|
}
|
||||||
Builder.CreateStore(CI, DestPtr, DestIsVolatile);
|
BuildAggStore(*this, CI, DestPtr, DestIsVolatile, false);
|
||||||
return RValue::getAggregate(DestPtr);
|
return RValue::getAggregate(DestPtr);
|
||||||
}
|
}
|
||||||
return RValue::get(CI);
|
return RValue::get(CI);
|
||||||
|
|
|
@ -23,7 +23,12 @@ extern "C" bool CGRectIsEmpty(CGRect);
|
||||||
CGRect virtualBounds;
|
CGRect virtualBounds;
|
||||||
|
|
||||||
// CHECK: [[SRC:%.*]] = call %struct.CGRect bitcast (i8* (i8*, i8*, ...)* @objc_msgSend
|
// 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) ? [self bounds] : virtualBounds;
|
dataRect = CGRectIsEmpty(virtualBounds) ? [self bounds] : virtualBounds;
|
||||||
dataRect = CGRectIsEmpty(virtualBounds) ? virtualBounds : self.bounds;
|
dataRect = CGRectIsEmpty(virtualBounds) ? virtualBounds : self.bounds;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче