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 = global i32 1
27int align0 = __alignof(struct s0);
28// CHECK: @align1 = global i32 4
29int align1 = __alignof(struct s1);
30// CHECK: @align2 = global i32 1
31int align2 = __alignof(struct s2);
32// CHECK: @align3 = global i32 1
33int align3 = __alignof(struct s3);
34
35// CHECK: @align0_x = global i32 1
36int align0_x = __alignof(((struct s0*) 0)->x);
37//
38// CHECK: @align1_x = global i32 1
39int align1_x = __alignof(((struct s1*) 0)->x);
40// CHECK: @align2_x = global i32 1
41int align2_x = __alignof(((struct s2*) 0)->x);
42// CHECK: @align3_x = global i32 1
43int align3_x = __alignof(((struct s3*) 0)->x);
44
45// CHECK: @align0_x0 = global i32 4
46int align0_x0 = __alignof(((struct s0*) 0)->x[0]);
47// CHECK: @align1_x0 = global i32 4
48int align1_x0 = __alignof(((struct s1*) 0)->x[0]);
49// CHECK: @align2_x0 = global i32 4
50int align2_x0 = __alignof(((struct s2*) 0)->x[0]);
51// CHECK: @align3_x0 = global i32 4
52int align3_x0 = __alignof(((struct s3*) 0)->x[0]);
53
54// CHECK-LABEL: define i32 @f0_a
55// CHECK:   load i32* %{{.*}}, align 1
56// CHECK: }
57// CHECK-LABEL: define i32 @f0_b
58// CHECK:   load 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 we are incompatible with GCC on this example.
68//
69// CHECK-LABEL: define i32 @f1_a
70// CHECK:   load i32* %{{.*}}, align 1
71// CHECK: }
72// CHECK-LABEL: define i32 @f1_b
73// CHECK:   load i32* %{{.*}}, align 4
74// CHECK: }
75
76// Note that we are incompatible with GCC on this example.
77//
78// CHECK-LABEL: define i32 @f1_c
79// CHECK:   load i32* %{{.*}}, align 4
80// CHECK: }
81// CHECK-LABEL: define i32 @f1_d
82// CHECK:   load i32* %{{.*}}, align 1
83// CHECK: }
84int f1_a(struct s1 *a) {
85  return a->x[1];
86}
87int f1_b(struct s1 *a) {
88  return *(a->x + 1);
89}
90int f1_c(struct s1 *a) {
91  return a->y;
92}
93int f1_d(struct s1 *a) {
94  return a->z;
95}
96
97// CHECK-LABEL: define i32 @f2_a
98// CHECK:   load i32* %{{.*}}, align 1
99// CHECK: }
100// CHECK-LABEL: define i32 @f2_b
101// CHECK:   load i32* %{{.*}}, align 4
102// CHECK: }
103// CHECK-LABEL: define i32 @f2_c
104// CHECK:   load i32* %{{.*}}, align 1
105// CHECK: }
106// CHECK-LABEL: define i32 @f2_d
107// CHECK:   load i32* %{{.*}}, align 1
108// CHECK: }
109int f2_a(struct s2 *a) {
110  return a->x[1];
111}
112int f2_b(struct s2 *a) {
113  return *(a->x + 1);
114}
115int f2_c(struct s2 *a) {
116  return a->y;
117}
118int f2_d(struct s2 *a) {
119  return a->z;
120}
121
122// CHECK-LABEL: define i32 @f3_a
123// CHECK:   load i32* %{{.*}}, align 1
124// CHECK: }
125// CHECK-LABEL: define i32 @f3_b
126// CHECK:   load i32* %{{.*}}, align 4
127// CHECK: }
128// CHECK-LABEL: define i32 @f3_c
129// CHECK:   load i32* %{{.*}}, align 1
130// CHECK: }
131// CHECK-LABEL: define i32 @f3_d
132// CHECK:   load i32* %{{.*}}, align 1
133// CHECK: }
134int f3_a(struct s3 *a) {
135  return a->x[1];
136}
137int f3_b(struct s3 *a) {
138  return *(a->x + 1);
139}
140int f3_c(struct s3 *a) {
141  return a->y;
142}
143int f3_d(struct s3 *a) {
144  return a->z;
145}
146
147// Verify we don't claim things are overaligned.
148//
149// CHECK-LABEL: define double @f4
150// CHECK:   load double* {{.*}}, align 8
151// CHECK: }
152extern double g4[5] __attribute__((aligned(16)));
153double f4() {
154  return g4[1];
155}
156