1// RUN: %clang_cc1 -triple x86_64-unk-unk -emit-llvm -Os -o %t %s
2// RUN: FileCheck < %t %s
3
4struct s0 {
5  unsigned int x[2] __attribute__((packed));
6};
7
8struct s1 {
9  unsigned int x[2] __attribute__((packed));
10  unsigned int y;
11  unsigned int z __attribute__((packed));
12};
13
14struct s2 {
15  unsigned int x[2] __attribute__((packed));
16  unsigned int y __attribute__((packed));
17  unsigned int z __attribute__((packed));
18};
19
20struct __attribute__((packed)) s3 {
21  unsigned int x[2];
22  unsigned int y;
23  unsigned int z;
24};
25
26// CHECK: @align0 = local_unnamed_addr global i32 1
27int align0 = __alignof(struct s0);
28// CHECK: @align1 = local_unnamed_addr global i32 4
29int align1 = __alignof(struct s1);
30// CHECK: @align2 = local_unnamed_addr global i32 1
31int align2 = __alignof(struct s2);
32// CHECK: @align3 = local_unnamed_addr global i32 1
33int align3 = __alignof(struct s3);
34
35// CHECK: @align0_x = local_unnamed_addr global i32 1
36int align0_x = __alignof(((struct s0*) 0)->x);
37//
38// CHECK: @align1_x = local_unnamed_addr global i32 1
39int align1_x = __alignof(((struct s1*) 0)->x);
40// CHECK: @align2_x = local_unnamed_addr global i32 1
41int align2_x = __alignof(((struct s2*) 0)->x);
42// CHECK: @align3_x = local_unnamed_addr global i32 1
43int align3_x = __alignof(((struct s3*) 0)->x);
44
45// CHECK: @align0_x0 = local_unnamed_addr global i32 4
46int align0_x0 = __alignof(((struct s0*) 0)->x[0]);
47// CHECK: @align1_x0 = local_unnamed_addr global i32 4
48int align1_x0 = __alignof(((struct s1*) 0)->x[0]);
49// CHECK: @align2_x0 = local_unnamed_addr global i32 4
50int align2_x0 = __alignof(((struct s2*) 0)->x[0]);
51// CHECK: @align3_x0 = local_unnamed_addr global i32 4
52int align3_x0 = __alignof(((struct s3*) 0)->x[0]);
53
54// CHECK-LABEL: define i32 @f0_a
55// CHECK:   load i32, i32* %{{.*}}, align 1
56// CHECK: }
57// CHECK-LABEL: define i32 @f0_b
58// CHECK:   load i32, i32* %{{.*}}, align 4
59// CHECK: }
60int f0_a(struct s0 *a) {
61  return a->x[1];
62}
63int f0_b(struct s0 *a) {
64  return *(a->x + 1);
65}
66
67// Note that 'y' still causes struct s1 to be four-byte aligned.
68
69// Note that we are incompatible with GCC on this example.
70//
71// CHECK-LABEL: define i32 @f1_a
72// CHECK:   load i32, i32* %{{.*}}, align 4
73// CHECK: }
74// CHECK-LABEL: define i32 @f1_b
75// CHECK:   load i32, i32* %{{.*}}, align 4
76// CHECK: }
77
78// Note that we are incompatible with GCC on this example.
79//
80// CHECK-LABEL: define i32 @f1_c
81// CHECK:   load i32, i32* %{{.*}}, align 4
82// CHECK: }
83// CHECK-LABEL: define i32 @f1_d
84// CHECK:   load i32, i32* %{{.*}}, align 4
85// CHECK: }
86int f1_a(struct s1 *a) {
87  return a->x[1];
88}
89int f1_b(struct s1 *a) {
90  return *(a->x + 1);
91}
92int f1_c(struct s1 *a) {
93  return a->y;
94}
95int f1_d(struct s1 *a) {
96  return a->z;
97}
98
99// CHECK-LABEL: define i32 @f2_a
100// CHECK:   load i32, i32* %{{.*}}, align 1
101// CHECK: }
102// CHECK-LABEL: define i32 @f2_b
103// CHECK:   load i32, i32* %{{.*}}, align 4
104// CHECK: }
105// CHECK-LABEL: define i32 @f2_c
106// CHECK:   load i32, i32* %{{.*}}, align 1
107// CHECK: }
108// CHECK-LABEL: define i32 @f2_d
109// CHECK:   load i32, i32* %{{.*}}, align 1
110// CHECK: }
111int f2_a(struct s2 *a) {
112  return a->x[1];
113}
114int f2_b(struct s2 *a) {
115  return *(a->x + 1);
116}
117int f2_c(struct s2 *a) {
118  return a->y;
119}
120int f2_d(struct s2 *a) {
121  return a->z;
122}
123
124// CHECK-LABEL: define i32 @f3_a
125// CHECK:   load i32, i32* %{{.*}}, align 1
126// CHECK: }
127// CHECK-LABEL: define i32 @f3_b
128// CHECK:   load i32, i32* %{{.*}}, align 4
129// CHECK: }
130// CHECK-LABEL: define i32 @f3_c
131// CHECK:   load i32, i32* %{{.*}}, align 1
132// CHECK: }
133// CHECK-LABEL: define i32 @f3_d
134// CHECK:   load i32, i32* %{{.*}}, align 1
135// CHECK: }
136int f3_a(struct s3 *a) {
137  return a->x[1];
138}
139int f3_b(struct s3 *a) {
140  return *(a->x + 1);
141}
142int f3_c(struct s3 *a) {
143  return a->y;
144}
145int f3_d(struct s3 *a) {
146  return a->z;
147}
148
149// Verify we don't claim things are overaligned.
150//
151// CHECK-LABEL: define double @f4
152// CHECK:   load double, double* {{.*}}, align 8
153// CHECK: }
154extern double g4[5] __attribute__((aligned(16)));
155double f4() {
156  return g4[1];
157}
158