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