| // RUN: %clang_cc1 -emit-llvm -triple x86_64-apple-darwin10 < %s | FileCheck %s |
| |
| struct Test1S { |
| long NumDecls; |
| long X; |
| long Y; |
| }; |
| struct Test2S { |
| long NumDecls; |
| long X; |
| }; |
| |
| // Make sure we don't generate extra memcpy for lvalues |
| void test1a(struct Test1S, struct Test2S); |
| // CHECK: define void @test1( |
| // CHECK-NOT: memcpy |
| // CHECK: call void @test1a |
| void test1(struct Test1S *A, struct Test2S *B) { |
| test1a(*A, *B); |
| } |
| |
| // The above gets tricker when the byval argument requires higher alignment |
| // than the natural alignment of the type in question. |
| // rdar://9483886 |
| |
| // Make sure we do generate a memcpy when we cannot guarantee alignment. |
| struct Test3S { |
| int a,b,c,d,e,f,g,h,i,j,k,l; |
| }; |
| void test2a(struct Test3S q); |
| // CHECK: define void @test2( |
| // CHECK: alloca %struct.Test3S, align 8 |
| // CHECK: memcpy |
| // CHECK: call void @test2a |
| void test2(struct Test3S *q) { |
| test2a(*q); |
| } |
| |
| // But make sure we don't generate a memcpy when we can guarantee alignment. |
| void fooey(void); |
| // CHECK: define void @test3( |
| // CHECK: alloca %struct.Test3S, align 8 |
| // CHECK: call void @fooey |
| // CHECK-NOT: memcpy |
| // CHECK: call void @test2a |
| // CHECK-NOT: memcpy |
| // CHECK: call void @test2a |
| void test3(struct Test3S a) { |
| struct Test3S b = a; |
| fooey(); |
| test2a(a); |
| test2a(b); |
| } |