1*67e74705SXin Li // RUN: %clang_cc1 %s -emit-llvm -o - -triple=x86_64-apple-darwin10 | FileCheck %s 2*67e74705SXin Li 3*67e74705SXin Li extern int int_source(); 4*67e74705SXin Li extern void int_sink(int x); 5*67e74705SXin Li 6*67e74705SXin Li namespace test0 { 7*67e74705SXin Li struct A { 8*67e74705SXin Li int aField; 9*67e74705SXin Li int bField; 10*67e74705SXin Li }; 11*67e74705SXin Li 12*67e74705SXin Li struct B { 13*67e74705SXin Li int onebit : 2; 14*67e74705SXin Li int twobit : 6; 15*67e74705SXin Li int intField; 16*67e74705SXin Li }; 17*67e74705SXin Li 18*67e74705SXin Li struct __attribute__((packed, aligned(2))) C : A, B { 19*67e74705SXin Li }; 20*67e74705SXin Li 21*67e74705SXin Li // These accesses should have alignment 4 because they're at offset 0 22*67e74705SXin Li // in a reference with an assumed alignment of 4. 23*67e74705SXin Li // CHECK-LABEL: @_ZN5test01aERNS_1BE a(B & b)24*67e74705SXin Li void a(B &b) { 25*67e74705SXin Li // CHECK: [[CALL:%.*]] = call i32 @_Z10int_sourcev() 26*67e74705SXin Li // CHECK: [[B_P:%.*]] = load [[B:%.*]]*, [[B]]** 27*67e74705SXin Li // CHECK: [[FIELD_P:%.*]] = bitcast [[B]]* [[B_P]] to i8* 28*67e74705SXin Li // CHECK: [[TRUNC:%.*]] = trunc i32 [[CALL]] to i8 29*67e74705SXin Li // CHECK: [[OLD_VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 4 30*67e74705SXin Li // CHECK: [[T0:%.*]] = and i8 [[TRUNC]], 3 31*67e74705SXin Li // CHECK: [[T1:%.*]] = and i8 [[OLD_VALUE]], -4 32*67e74705SXin Li // CHECK: [[T2:%.*]] = or i8 [[T1]], [[T0]] 33*67e74705SXin Li // CHECK: store i8 [[T2]], i8* [[FIELD_P]], align 4 34*67e74705SXin Li b.onebit = int_source(); 35*67e74705SXin Li 36*67e74705SXin Li // CHECK: [[B_P:%.*]] = load [[B]]*, [[B]]** 37*67e74705SXin Li // CHECK: [[FIELD_P:%.*]] = bitcast [[B]]* [[B_P]] to i8* 38*67e74705SXin Li // CHECK: [[VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 4 39*67e74705SXin Li // CHECK: [[T0:%.*]] = shl i8 [[VALUE]], 6 40*67e74705SXin Li // CHECK: [[T1:%.*]] = ashr i8 [[T0]], 6 41*67e74705SXin Li // CHECK: [[T2:%.*]] = sext i8 [[T1]] to i32 42*67e74705SXin Li // CHECK: call void @_Z8int_sinki(i32 [[T2]]) 43*67e74705SXin Li int_sink(b.onebit); 44*67e74705SXin Li } 45*67e74705SXin Li 46*67e74705SXin Li // These accesses should have alignment 2 because they're at offset 8 47*67e74705SXin Li // in a reference/pointer with an assumed alignment of 2. 48*67e74705SXin Li // CHECK-LABEL: @_ZN5test01bERNS_1CE b(C & c)49*67e74705SXin Li void b(C &c) { 50*67e74705SXin Li // CHECK: [[CALL:%.*]] = call i32 @_Z10int_sourcev() 51*67e74705SXin Li // CHECK: [[C_P:%.*]] = load [[C:%.*]]*, [[C]]** 52*67e74705SXin Li // CHECK: [[T0:%.*]] = bitcast [[C]]* [[C_P]] to i8* 53*67e74705SXin Li // CHECK: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 8 54*67e74705SXin Li // CHECK: [[B_P:%.*]] = bitcast i8* [[T1]] to [[B]]* 55*67e74705SXin Li // CHECK: [[FIELD_P:%.*]] = bitcast [[B]]* [[B_P]] to i8* 56*67e74705SXin Li // CHECK: [[TRUNC:%.*]] = trunc i32 [[CALL]] to i8 57*67e74705SXin Li // CHECK: [[OLD_VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 2 58*67e74705SXin Li // CHECK: [[T0:%.*]] = and i8 [[TRUNC]], 3 59*67e74705SXin Li // CHECK: [[T1:%.*]] = and i8 [[OLD_VALUE]], -4 60*67e74705SXin Li // CHECK: [[T2:%.*]] = or i8 [[T1]], [[T0]] 61*67e74705SXin Li // CHECK: store i8 [[T2]], i8* [[FIELD_P]], align 2 62*67e74705SXin Li c.onebit = int_source(); 63*67e74705SXin Li 64*67e74705SXin Li // CHECK: [[C_P:%.*]] = load [[C]]*, [[C]]** 65*67e74705SXin Li // CHECK: [[T0:%.*]] = bitcast [[C]]* [[C_P]] to i8* 66*67e74705SXin Li // CHECK: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 8 67*67e74705SXin Li // CHECK: [[B_P:%.*]] = bitcast i8* [[T1]] to [[B]]* 68*67e74705SXin Li // CHECK: [[FIELD_P:%.*]] = bitcast [[B]]* [[B_P]] to i8* 69*67e74705SXin Li // CHECK: [[VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 2 70*67e74705SXin Li // CHECK: [[T0:%.*]] = shl i8 [[VALUE]], 6 71*67e74705SXin Li // CHECK: [[T1:%.*]] = ashr i8 [[T0]], 6 72*67e74705SXin Li // CHECK: [[T2:%.*]] = sext i8 [[T1]] to i32 73*67e74705SXin Li // CHECK: call void @_Z8int_sinki(i32 [[T2]]) 74*67e74705SXin Li int_sink(c.onebit); 75*67e74705SXin Li } 76*67e74705SXin Li 77*67e74705SXin Li // CHECK-LABEL: @_ZN5test01cEPNS_1CE c(C * c)78*67e74705SXin Li void c(C *c) { 79*67e74705SXin Li // CHECK: [[CALL:%.*]] = call i32 @_Z10int_sourcev() 80*67e74705SXin Li // CHECK: [[C_P:%.*]] = load [[C]]*, [[C]]** 81*67e74705SXin Li // CHECK: [[T0:%.*]] = bitcast [[C]]* [[C_P]] to i8* 82*67e74705SXin Li // CHECK: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 8 83*67e74705SXin Li // CHECK: [[B_P:%.*]] = bitcast i8* [[T1]] to [[B]]* 84*67e74705SXin Li // CHECK: [[FIELD_P:%.*]] = bitcast [[B]]* [[B_P]] to i8* 85*67e74705SXin Li // CHECK: [[TRUNC:%.*]] = trunc i32 [[CALL]] to i8 86*67e74705SXin Li // CHECK: [[OLD_VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 2 87*67e74705SXin Li // CHECK: [[T0:%.*]] = and i8 [[TRUNC]], 3 88*67e74705SXin Li // CHECK: [[T1:%.*]] = and i8 [[OLD_VALUE]], -4 89*67e74705SXin Li // CHECK: [[T2:%.*]] = or i8 [[T1]], [[T0]] 90*67e74705SXin Li // CHECK: store i8 [[T2]], i8* [[FIELD_P]], align 2 91*67e74705SXin Li c->onebit = int_source(); 92*67e74705SXin Li 93*67e74705SXin Li // CHECK: [[C_P:%.*]] = load [[C:%.*]]*, [[C]]** 94*67e74705SXin Li // CHECK: [[T0:%.*]] = bitcast [[C]]* [[C_P]] to i8* 95*67e74705SXin Li // CHECK: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 8 96*67e74705SXin Li // CHECK: [[B_P:%.*]] = bitcast i8* [[T1]] to [[B:%.*]]* 97*67e74705SXin Li // CHECK: [[FIELD_P:%.*]] = bitcast [[B]]* [[B_P]] to i8* 98*67e74705SXin Li // CHECK: [[VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 2 99*67e74705SXin Li // CHECK: [[T0:%.*]] = shl i8 [[VALUE]], 6 100*67e74705SXin Li // CHECK: [[T1:%.*]] = ashr i8 [[T0]], 6 101*67e74705SXin Li // CHECK: [[T2:%.*]] = sext i8 [[T1]] to i32 102*67e74705SXin Li // CHECK: call void @_Z8int_sinki(i32 [[T2]]) 103*67e74705SXin Li int_sink(c->onebit); 104*67e74705SXin Li } 105*67e74705SXin Li 106*67e74705SXin Li // These accesses should have alignment 2 because they're at offset 8 107*67e74705SXin Li // in an alignment-2 variable. 108*67e74705SXin Li // CHECK-LABEL: @_ZN5test01dEv d()109*67e74705SXin Li void d() { 110*67e74705SXin Li // CHECK: [[C_P:%.*]] = alloca [[C:%.*]], align 2 111*67e74705SXin Li C c; 112*67e74705SXin Li 113*67e74705SXin Li // CHECK: [[CALL:%.*]] = call i32 @_Z10int_sourcev() 114*67e74705SXin Li // CHECK: [[T0:%.*]] = bitcast [[C]]* [[C_P]] to i8* 115*67e74705SXin Li // CHECK: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 8 116*67e74705SXin Li // CHECK: [[B_P:%.*]] = bitcast i8* [[T1]] to [[B]]* 117*67e74705SXin Li // CHECK: [[FIELD_P:%.*]] = bitcast [[B]]* [[B_P]] to i8* 118*67e74705SXin Li // CHECK: [[TRUNC:%.*]] = trunc i32 [[CALL]] to i8 119*67e74705SXin Li // CHECK: [[OLD_VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 2 120*67e74705SXin Li // CHECK: [[T0:%.*]] = and i8 [[TRUNC]], 3 121*67e74705SXin Li // CHECK: [[T1:%.*]] = and i8 [[OLD_VALUE]], -4 122*67e74705SXin Li // CHECK: [[T2:%.*]] = or i8 [[T1]], [[T0]] 123*67e74705SXin Li // CHECK: store i8 [[T2]], i8* [[FIELD_P]], align 2 124*67e74705SXin Li c.onebit = int_source(); 125*67e74705SXin Li 126*67e74705SXin Li // CHECK: [[T0:%.*]] = bitcast [[C]]* [[C_P]] to i8* 127*67e74705SXin Li // CHECK: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 8 128*67e74705SXin Li // CHECK: [[B_P:%.*]] = bitcast i8* [[T1]] to [[B:%.*]]* 129*67e74705SXin Li // CHECK: [[FIELD_P:%.*]] = bitcast [[B]]* [[B_P]] to i8* 130*67e74705SXin Li // CHECK: [[VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 2 131*67e74705SXin Li // CHECK: [[T0:%.*]] = shl i8 [[VALUE]], 6 132*67e74705SXin Li // CHECK: [[T1:%.*]] = ashr i8 [[T0]], 6 133*67e74705SXin Li // CHECK: [[T2:%.*]] = sext i8 [[T1]] to i32 134*67e74705SXin Li // CHECK: call void @_Z8int_sinki(i32 [[T2]]) 135*67e74705SXin Li int_sink(c.onebit); 136*67e74705SXin Li } 137*67e74705SXin Li 138*67e74705SXin Li // These accesses should have alignment 8 because they're at offset 8 139*67e74705SXin Li // in an alignment-16 variable. 140*67e74705SXin Li // CHECK-LABEL: @_ZN5test01eEv e()141*67e74705SXin Li void e() { 142*67e74705SXin Li // CHECK: [[C_P:%.*]] = alloca [[C:%.*]], align 16 143*67e74705SXin Li __attribute__((aligned(16))) C c; 144*67e74705SXin Li 145*67e74705SXin Li // CHECK: [[CALL:%.*]] = call i32 @_Z10int_sourcev() 146*67e74705SXin Li // CHECK: [[T0:%.*]] = bitcast [[C]]* [[C_P]] to i8* 147*67e74705SXin Li // CHECK: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 8 148*67e74705SXin Li // CHECK: [[B_P:%.*]] = bitcast i8* [[T1]] to [[B]]* 149*67e74705SXin Li // CHECK: [[FIELD_P:%.*]] = bitcast [[B]]* [[B_P]] to i8* 150*67e74705SXin Li // CHECK: [[TRUNC:%.*]] = trunc i32 [[CALL]] to i8 151*67e74705SXin Li // CHECK: [[OLD_VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 8 152*67e74705SXin Li // CHECK: [[T0:%.*]] = and i8 [[TRUNC]], 3 153*67e74705SXin Li // CHECK: [[T1:%.*]] = and i8 [[OLD_VALUE]], -4 154*67e74705SXin Li // CHECK: [[T2:%.*]] = or i8 [[T1]], [[T0]] 155*67e74705SXin Li // CHECK: store i8 [[T2]], i8* [[FIELD_P]], align 8 156*67e74705SXin Li c.onebit = int_source(); 157*67e74705SXin Li 158*67e74705SXin Li // CHECK: [[T0:%.*]] = bitcast [[C]]* [[C_P]] to i8* 159*67e74705SXin Li // CHECK: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 8 160*67e74705SXin Li // CHECK: [[B_P:%.*]] = bitcast i8* [[T1]] to [[B:%.*]]* 161*67e74705SXin Li // CHECK: [[FIELD_P:%.*]] = bitcast [[B]]* [[B_P]] to i8* 162*67e74705SXin Li // CHECK: [[VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 8 163*67e74705SXin Li // CHECK: [[T0:%.*]] = shl i8 [[VALUE]], 6 164*67e74705SXin Li // CHECK: [[T1:%.*]] = ashr i8 [[T0]], 6 165*67e74705SXin Li // CHECK: [[T2:%.*]] = sext i8 [[T1]] to i32 166*67e74705SXin Li // CHECK: call void @_Z8int_sinki(i32 [[T2]]) 167*67e74705SXin Li int_sink(c.onebit); 168*67e74705SXin Li } 169*67e74705SXin Li } 170*67e74705SXin Li 171*67e74705SXin Li namespace test1 { 172*67e74705SXin Li struct Array { 173*67e74705SXin Li int elts[4]; 174*67e74705SXin Li }; 175*67e74705SXin Li 176*67e74705SXin Li struct A { 177*67e74705SXin Li __attribute__((aligned(16))) Array aArray; 178*67e74705SXin Li }; 179*67e74705SXin Li 180*67e74705SXin Li struct B : virtual A { 181*67e74705SXin Li void *bPointer; // puts bArray at offset 16 182*67e74705SXin Li Array bArray; 183*67e74705SXin Li }; 184*67e74705SXin Li 185*67e74705SXin Li struct C : virtual A { // must be viable as primary base 186*67e74705SXin Li // Non-empty, nv-size not a multiple of 16. 187*67e74705SXin Li void *cPointer1; 188*67e74705SXin Li void *cPointer2; 189*67e74705SXin Li }; 190*67e74705SXin Li 191*67e74705SXin Li // Proof of concept that the non-virtual components of B do not have 192*67e74705SXin Li // to be 16-byte-aligned. 193*67e74705SXin Li struct D : C, B {}; 194*67e74705SXin Li 195*67e74705SXin Li // For the following tests, we want to assign into a variable whose 196*67e74705SXin Li // alignment is high enough that it will absolutely not be the 197*67e74705SXin Li // constraint on the memcpy alignment. 198*67e74705SXin Li typedef __attribute__((aligned(64))) Array AlignedArray; 199*67e74705SXin Li 200*67e74705SXin Li // CHECK-LABEL: @_ZN5test11aERNS_1AE a(A & a)201*67e74705SXin Li void a(A &a) { 202*67e74705SXin Li // CHECK: [[RESULT:%.*]] = alloca [[ARRAY:%.*]], align 64 203*67e74705SXin Li // CHECK: [[A_P:%.*]] = load [[A:%.*]]*, [[A]]** 204*67e74705SXin Li // CHECK: [[ARRAY_P:%.*]] = getelementptr inbounds [[A]], [[A]]* [[A_P]], i32 0, i32 0 205*67e74705SXin Li // CHECK: [[T0:%.*]] = bitcast [[ARRAY]]* [[RESULT]] to i8* 206*67e74705SXin Li // CHECK: [[T1:%.*]] = bitcast [[ARRAY]]* [[ARRAY_P]] to i8* 207*67e74705SXin Li // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T0]], i8* [[T1]], i64 16, i32 16, i1 false) 208*67e74705SXin Li AlignedArray result = a.aArray; 209*67e74705SXin Li } 210*67e74705SXin Li 211*67e74705SXin Li // CHECK-LABEL: @_ZN5test11bERNS_1BE b(B & b)212*67e74705SXin Li void b(B &b) { 213*67e74705SXin Li // CHECK: [[RESULT:%.*]] = alloca [[ARRAY]], align 64 214*67e74705SXin Li // CHECK: [[B_P:%.*]] = load [[B:%.*]]*, [[B]]** 215*67e74705SXin Li // CHECK: [[VPTR_P:%.*]] = bitcast [[B]]* [[B_P]] to i8** 216*67e74705SXin Li // CHECK: [[VPTR:%.*]] = load i8*, i8** [[VPTR_P]], align 8 217*67e74705SXin Li // CHECK: [[T0:%.*]] = getelementptr i8, i8* [[VPTR]], i64 -24 218*67e74705SXin Li // CHECK: [[OFFSET_P:%.*]] = bitcast i8* [[T0]] to i64* 219*67e74705SXin Li // CHECK: [[OFFSET:%.*]] = load i64, i64* [[OFFSET_P]], align 8 220*67e74705SXin Li // CHECK: [[T0:%.*]] = bitcast [[B]]* [[B_P]] to i8* 221*67e74705SXin Li // CHECK: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 [[OFFSET]] 222*67e74705SXin Li // CHECK: [[A_P:%.*]] = bitcast i8* [[T1]] to [[A]]* 223*67e74705SXin Li // CHECK: [[ARRAY_P:%.*]] = getelementptr inbounds [[A]], [[A]]* [[A_P]], i32 0, i32 0 224*67e74705SXin Li // CHECK: [[T0:%.*]] = bitcast [[ARRAY]]* [[RESULT]] to i8* 225*67e74705SXin Li // CHECK: [[T1:%.*]] = bitcast [[ARRAY]]* [[ARRAY_P]] to i8* 226*67e74705SXin Li // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T0]], i8* [[T1]], i64 16, i32 16, i1 false) 227*67e74705SXin Li AlignedArray result = b.aArray; 228*67e74705SXin Li } 229*67e74705SXin Li 230*67e74705SXin Li // CHECK-LABEL: @_ZN5test11cERNS_1BE c(B & b)231*67e74705SXin Li void c(B &b) { 232*67e74705SXin Li // CHECK: [[RESULT:%.*]] = alloca [[ARRAY]], align 64 233*67e74705SXin Li // CHECK: [[B_P:%.*]] = load [[B]]*, [[B]]** 234*67e74705SXin Li // CHECK: [[ARRAY_P:%.*]] = getelementptr inbounds [[B]], [[B]]* [[B_P]], i32 0, i32 2 235*67e74705SXin Li // CHECK: [[T0:%.*]] = bitcast [[ARRAY]]* [[RESULT]] to i8* 236*67e74705SXin Li // CHECK: [[T1:%.*]] = bitcast [[ARRAY]]* [[ARRAY_P]] to i8* 237*67e74705SXin Li // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T0]], i8* [[T1]], i64 16, i32 8, i1 false) 238*67e74705SXin Li AlignedArray result = b.bArray; 239*67e74705SXin Li } 240*67e74705SXin Li 241*67e74705SXin Li // CHECK-LABEL: @_ZN5test11dEPNS_1BE d(B * b)242*67e74705SXin Li void d(B *b) { 243*67e74705SXin Li // CHECK: [[RESULT:%.*]] = alloca [[ARRAY]], align 64 244*67e74705SXin Li // CHECK: [[B_P:%.*]] = load [[B]]*, [[B]]** 245*67e74705SXin Li // CHECK: [[ARRAY_P:%.*]] = getelementptr inbounds [[B]], [[B]]* [[B_P]], i32 0, i32 2 246*67e74705SXin Li // CHECK: [[T0:%.*]] = bitcast [[ARRAY]]* [[RESULT]] to i8* 247*67e74705SXin Li // CHECK: [[T1:%.*]] = bitcast [[ARRAY]]* [[ARRAY_P]] to i8* 248*67e74705SXin Li // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T0]], i8* [[T1]], i64 16, i32 8, i1 false) 249*67e74705SXin Li AlignedArray result = b->bArray; 250*67e74705SXin Li } 251*67e74705SXin Li 252*67e74705SXin Li // CHECK-LABEL: @_ZN5test11eEv e()253*67e74705SXin Li void e() { 254*67e74705SXin Li // CHECK: [[B_P:%.*]] = alloca [[B]], align 16 255*67e74705SXin Li // CHECK: [[RESULT:%.*]] = alloca [[ARRAY]], align 64 256*67e74705SXin Li // CHECK: [[ARRAY_P:%.*]] = getelementptr inbounds [[B]], [[B]]* [[B_P]], i32 0, i32 2 257*67e74705SXin Li // CHECK: [[T0:%.*]] = bitcast [[ARRAY]]* [[RESULT]] to i8* 258*67e74705SXin Li // CHECK: [[T1:%.*]] = bitcast [[ARRAY]]* [[ARRAY_P]] to i8* 259*67e74705SXin Li // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T0]], i8* [[T1]], i64 16, i32 16, i1 false) 260*67e74705SXin Li B b; 261*67e74705SXin Li AlignedArray result = b.bArray; 262*67e74705SXin Li } 263*67e74705SXin Li 264*67e74705SXin Li // CHECK-LABEL: @_ZN5test11fEv f()265*67e74705SXin Li void f() { 266*67e74705SXin Li // TODO: we should devirtualize this derived-to-base conversion. 267*67e74705SXin Li // CHECK: [[D_P:%.*]] = alloca [[D:%.*]], align 16 268*67e74705SXin Li // CHECK: [[RESULT:%.*]] = alloca [[ARRAY]], align 64 269*67e74705SXin Li // CHECK: [[VPTR_P:%.*]] = bitcast [[D]]* [[D_P]] to i8** 270*67e74705SXin Li // CHECK: [[VPTR:%.*]] = load i8*, i8** [[VPTR_P]], align 16 271*67e74705SXin Li // CHECK: [[T0:%.*]] = getelementptr i8, i8* [[VPTR]], i64 -24 272*67e74705SXin Li // CHECK: [[OFFSET_P:%.*]] = bitcast i8* [[T0]] to i64* 273*67e74705SXin Li // CHECK: [[OFFSET:%.*]] = load i64, i64* [[OFFSET_P]], align 8 274*67e74705SXin Li // CHECK: [[T0:%.*]] = bitcast [[D]]* [[D_P]] to i8* 275*67e74705SXin Li // CHECK: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 [[OFFSET]] 276*67e74705SXin Li // CHECK: [[A_P:%.*]] = bitcast i8* [[T1]] to [[A]]* 277*67e74705SXin Li // CHECK: [[ARRAY_P:%.*]] = getelementptr inbounds [[A]], [[A]]* [[A_P]], i32 0, i32 0 278*67e74705SXin Li // CHECK: [[T0:%.*]] = bitcast [[ARRAY]]* [[RESULT]] to i8* 279*67e74705SXin Li // CHECK: [[T1:%.*]] = bitcast [[ARRAY]]* [[ARRAY_P]] to i8* 280*67e74705SXin Li // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T0]], i8* [[T1]], i64 16, i32 16, i1 false) 281*67e74705SXin Li D d; 282*67e74705SXin Li AlignedArray result = d.aArray; 283*67e74705SXin Li } 284*67e74705SXin Li 285*67e74705SXin Li // CHECK-LABEL: @_ZN5test11gEv g()286*67e74705SXin Li void g() { 287*67e74705SXin Li // CHECK: [[D_P:%.*]] = alloca [[D]], align 16 288*67e74705SXin Li // CHECK: [[RESULT:%.*]] = alloca [[ARRAY]], align 64 289*67e74705SXin Li // CHECK: [[T0:%.*]] = bitcast [[D]]* [[D_P]] to i8* 290*67e74705SXin Li // CHECK: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 24 291*67e74705SXin Li // CHECK: [[B_P:%.*]] = bitcast i8* [[T1]] to [[B:%.*]]* 292*67e74705SXin Li // CHECK: [[ARRAY_P:%.*]] = getelementptr inbounds [[B]], [[B]]* [[B_P]], i32 0, i32 2 293*67e74705SXin Li // CHECK: [[T0:%.*]] = bitcast [[ARRAY]]* [[RESULT]] to i8* 294*67e74705SXin Li // CHECK: [[T1:%.*]] = bitcast [[ARRAY]]* [[ARRAY_P]] to i8* 295*67e74705SXin Li // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[T0]], i8* [[T1]], i64 16, i32 8, i1 false) 296*67e74705SXin Li D d; 297*67e74705SXin Li AlignedArray result = d.bArray; 298*67e74705SXin Li } 299*67e74705SXin Li } 300