diff options
author | Chris Lattner <sabre@nondot.org> | 2010-06-27 06:04:18 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2010-06-27 06:04:18 +0000 |
commit | e7bb777caf478ac8b096bd6a0c14d78ea8b2f5be (patch) | |
tree | a15f5ec940404fc5ad19f011498a4d6c73bf33fa | |
parent | 08dd2a0e4c6b3c7cb601e5053eb02cb7d084f87e (diff) |
Same patch as the previous on the store side. Before we compiled this:
struct DeclGroup {
unsigned NumDecls;
};
int foo(DeclGroup D) {
return D.NumDecls;
}
to:
%struct.DeclGroup = type { i32 }
define i32 @_Z3foo9DeclGroup(i64) nounwind ssp noredzone {
entry:
%D = alloca %struct.DeclGroup, align 4 ; <%struct.DeclGroup*> [#uses=2]
%tmp = alloca i64 ; <i64*> [#uses=2]
store i64 %0, i64* %tmp
%1 = bitcast i64* %tmp to %struct.DeclGroup* ; <%struct.DeclGroup*> [#uses=1]
%2 = load %struct.DeclGroup* %1, align 1 ; <%struct.DeclGroup> [#uses=1]
store %struct.DeclGroup %2, %struct.DeclGroup* %D
%tmp1 = getelementptr inbounds %struct.DeclGroup* %D, i32 0, i32 0 ; <i32*> [#uses=1]
%tmp2 = load i32* %tmp1 ; <i32> [#uses=1]
ret i32 %tmp2
}
which caused fast isel bailouts due to the FCA load/store of %2. Now
we generate this just blissful code:
%struct.DeclGroup = type { i32 }
define i32 @_Z3foo9DeclGroup(i64) nounwind ssp noredzone {
entry:
%D = alloca %struct.DeclGroup, align 4 ; <%struct.DeclGroup*> [#uses=2]
%tmp = alloca i64 ; <i64*> [#uses=2]
%coerce.dive = getelementptr %struct.DeclGroup* %D, i32 0, i32 0 ; <i32*> [#uses=1]
store i64 %0, i64* %tmp
%1 = bitcast i64* %tmp to i32* ; <i32*> [#uses=1]
%2 = load i32* %1, align 1 ; <i32> [#uses=1]
store i32 %2, i32* %coerce.dive
%tmp1 = getelementptr inbounds %struct.DeclGroup* %D, i32 0, i32 0 ; <i32*> [#uses=1]
%tmp2 = load i32* %tmp1 ; <i32> [#uses=1]
ret i32 %tmp2
}
This avoids fastisel bailing out and is groundwork for future patch.
This reduces bailouts on CGStmt.ll to 911 from 935.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@106974 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/CodeGen/CGCall.cpp | 20 | ||||
-rw-r--r-- | test/CodeGen/x86_64-arguments.c | 6 |
2 files changed, 16 insertions, 10 deletions
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index 7ec5e303dc..7835505dcf 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -345,14 +345,14 @@ CodeGenFunction::ExpandTypeToArgs(QualType Ty, RValue RV, } } -/// EnterStructPointerForCoercedLoad - Given a pointer to a struct where we are +/// EnterStructPointerForCoercedAccess - Given a struct pointer that we are /// accessing some number of bytes out of it, try to gep into the struct to get /// at its inner goodness. Dive as deep as possible without entering an element /// with an in-memory size smaller than DstSize. static llvm::Value * -EnterStructPointerForCoercedLoad(llvm::Value *SrcPtr, - const llvm::StructType *SrcSTy, - uint64_t DstSize, CodeGenFunction &CGF) { +EnterStructPointerForCoercedAccess(llvm::Value *SrcPtr, + const llvm::StructType *SrcSTy, + uint64_t DstSize, CodeGenFunction &CGF) { // We can't dive into a zero-element struct. if (SrcSTy->getNumElements() == 0) return SrcPtr; @@ -373,7 +373,7 @@ EnterStructPointerForCoercedLoad(llvm::Value *SrcPtr, const llvm::Type *SrcTy = cast<llvm::PointerType>(SrcPtr->getType())->getElementType(); if (const llvm::StructType *SrcSTy = dyn_cast<llvm::StructType>(SrcTy)) - return EnterStructPointerForCoercedLoad(SrcPtr, SrcSTy, DstSize, CGF); + return EnterStructPointerForCoercedAccess(SrcPtr, SrcSTy, DstSize, CGF); return SrcPtr; } @@ -394,7 +394,7 @@ static llvm::Value *CreateCoercedLoad(llvm::Value *SrcPtr, uint64_t DstSize = CGF.CGM.getTargetData().getTypeAllocSize(Ty); if (const llvm::StructType *SrcSTy = dyn_cast<llvm::StructType>(SrcTy)) { - SrcPtr = EnterStructPointerForCoercedLoad(SrcPtr, SrcSTy, DstSize, CGF); + SrcPtr = EnterStructPointerForCoercedAccess(SrcPtr, SrcSTy, DstSize, CGF); SrcTy = cast<llvm::PointerType>(SrcPtr->getType())->getElementType(); } @@ -438,10 +438,16 @@ static void CreateCoercedStore(llvm::Value *Src, bool DstIsVolatile, CodeGenFunction &CGF) { const llvm::Type *SrcTy = Src->getType(); + uint64_t SrcSize = CGF.CGM.getTargetData().getTypeAllocSize(SrcTy); + const llvm::Type *DstTy = cast<llvm::PointerType>(DstPtr->getType())->getElementType(); - uint64_t SrcSize = CGF.CGM.getTargetData().getTypeAllocSize(SrcTy); + if (const llvm::StructType *DstSTy = dyn_cast<llvm::StructType>(DstTy)) { + DstPtr = EnterStructPointerForCoercedAccess(DstPtr, DstSTy, SrcSize, CGF); + DstTy = cast<llvm::PointerType>(DstPtr->getType())->getElementType(); + } + uint64_t DstSize = CGF.CGM.getTargetData().getTypeAllocSize(DstTy); // If store is legal, just bitcast the src pointer. diff --git a/test/CodeGen/x86_64-arguments.c b/test/CodeGen/x86_64-arguments.c index 47b2eb1585..b53dfdf93d 100644 --- a/test/CodeGen/x86_64-arguments.c +++ b/test/CodeGen/x86_64-arguments.c @@ -93,9 +93,9 @@ void f17(float a, float b, float c, float d, float e, float f, float g, float h, long double X) {} // Check for valid coercion. -// CHECK: [[f18_t0:%.*]] = bitcast i64* {{.*}} to %struct.f18_s0* -// CHECK: [[f18_t1:%.*]] = load %struct.f18_s0* [[f18_t0]], align 1 -// CHECK: store %struct.f18_s0 [[f18_t1]], %struct.f18_s0* %f18_arg1 +// CHECK: [[f18_t0:%.*]] = bitcast i64* {{.*}} to i32* +// CHECK: [[f18_t1:%.*]] = load i32* [[f18_t0]], align 1 +// CHECK: store i32 [[f18_t1]], i32* struct f18_s0 { int f0; }; void f18(int a, struct f18_s0 f18_arg1) { while (1) {} } |