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