diff options
author | Chris Lattner <sabre@nondot.org> | 2010-07-29 07:43:55 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2010-07-29 07:43:55 +0000 |
commit | 98076a25ced0c70ef088b6577276409519170f74 (patch) | |
tree | c2860fdfdba060adadc62c86ca5d87a21fe2723c /clang | |
parent | c8b7b53a1e7e68a730b04669827ecaf799e103ec (diff) | |
download | bcm5719-llvm-98076a25ced0c70ef088b6577276409519170f74.tar.gz bcm5719-llvm-98076a25ced0c70ef088b6577276409519170f74.zip |
This is a little bit far, but optimize cases like:
struct a {
struct c {
double x;
int y;
} x[1];
};
void foo(struct a A) {
}
into:
define void @foo(double %A.coerce0, i32 %A.coerce1) nounwind {
entry:
%A = alloca %struct.a, align 8 ; <%struct.a*> [#uses=1]
%0 = bitcast %struct.a* %A to %struct.c* ; <%struct.c*> [#uses=2]
%1 = getelementptr %struct.c* %0, i32 0, i32 0 ; <double*> [#uses=1]
store double %A.coerce0, double* %1
%2 = getelementptr %struct.c* %0, i32 0, i32 1 ; <i32*> [#uses=1]
store i32 %A.coerce1, i32* %2
instead of:
define void @foo(double %A.coerce0, i64 %A.coerce1) nounwind {
entry:
%A = alloca %struct.a, align 8 ; <%struct.a*> [#uses=1]
%0 = bitcast %struct.a* %A to %0* ; <%0*> [#uses=2]
%1 = getelementptr %0* %0, i32 0, i32 0 ; <double*> [#uses=1]
store double %A.coerce0, double* %1
%2 = getelementptr %0* %0, i32 0, i32 1 ; <i64*> [#uses=1]
store i64 %A.coerce1, i64* %2
I only do this now because I never want to look at this code again :)
llvm-svn: 109738
Diffstat (limited to 'clang')
-rw-r--r-- | clang/lib/CodeGen/TargetInfo.cpp | 29 | ||||
-rw-r--r-- | clang/test/CodeGen/x86_64-arguments.c | 10 |
2 files changed, 36 insertions, 3 deletions
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index 6b262ebedaa..8729da9e175 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -1226,9 +1226,24 @@ static bool BitsContainNoUserData(QualType Ty, unsigned StartBit, if (TySize <= StartBit) return true; - //if (const ConstantArrayType *AT = Context.getAsConstantArrayType(Ty)) { - // TODO. - //} + if (const ConstantArrayType *AT = Context.getAsConstantArrayType(Ty)) { + unsigned EltSize = (unsigned)Context.getTypeSize(AT->getElementType()); + unsigned NumElts = (unsigned)AT->getSize().getZExtValue(); + + // Check each element to see if the element overlaps with the queried range. + for (unsigned i = 0; i != NumElts; ++i) { + // If the element is after the span we care about, then we're done.. + unsigned EltOffset = i*EltSize; + if (EltOffset >= EndBit) break; + + unsigned EltStart = EltOffset < StartBit ? StartBit-EltOffset :0; + if (!BitsContainNoUserData(AT->getElementType(), EltStart, + EndBit-EltOffset, Context)) + return false; + } + // If it overlaps no elements, then it is safe to process as padding. + return true; + } if (const RecordType *RT = Ty->getAs<RecordType>()) { const RecordDecl *RD = RT->getDecl(); @@ -1332,6 +1347,14 @@ Get8ByteTypeAtOffset(const llvm::Type *IRType, unsigned IROffset, } } + if (const llvm::ArrayType *ATy = dyn_cast<llvm::ArrayType>(IRType)) { + const llvm::Type *EltTy = ATy->getElementType(); + unsigned EltSize = getTargetData().getTypeAllocSize(EltTy); + unsigned EltOffset = IROffset/EltSize*EltSize; + return Get8ByteTypeAtOffset(EltTy, IROffset-EltOffset, SourceTy, + SourceOffset); + } + // Okay, we don't have any better idea of what to pass, so we pass this in an // integer register that isn't too big to fit the rest of the struct. uint64_t TySizeInBytes = diff --git a/clang/test/CodeGen/x86_64-arguments.c b/clang/test/CodeGen/x86_64-arguments.c index 1a5db3a9557..5da5744b6e3 100644 --- a/clang/test/CodeGen/x86_64-arguments.c +++ b/clang/test/CodeGen/x86_64-arguments.c @@ -194,3 +194,13 @@ void f28(struct f28c C) { // CHECK: define void @f28(double %C.coerce0, i32 %C.coerce1) } +struct f29a { + struct c { + double x; + int y; + } x[1]; +}; + +void f29a(struct f29a A) { + // CHECK: define void @f29a(double %A.coerce0, i32 %A.coerce1) +} |