1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S < %s | FileCheck %s
3
4%struct.Counters = type { i64, i64, i64, [8 x i8] }
5
6@m = global i64 3, align 8
7@counters = global %struct.Counters zeroinitializer, align 16
8
9define i32 @align_both_equal() local_unnamed_addr {
10; CHECK-LABEL: @align_both_equal(
11; CHECK-NEXT:  entry:
12; CHECK-NEXT:    [[TMP0:%.*]] = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds ([[STRUCT_COUNTERS:%.*]], %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
13; CHECK-NEXT:    [[TMP1:%.*]] = add nsw <2 x i64> [[TMP0]], <i64 1, i64 1>
14; CHECK-NEXT:    store <2 x i64> [[TMP1]], <2 x i64>* bitcast (i64* getelementptr inbounds ([[STRUCT_COUNTERS]], %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
15; CHECK-NEXT:    [[TMP2:%.*]] = load i64, i64* @m, align 8
16; CHECK-NEXT:    [[AND:%.*]] = and i64 [[TMP2]], 1
17; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i64 [[AND]], 0
18; CHECK-NEXT:    [[TMP3:%.*]] = add nsw <2 x i64> [[TMP0]], <i64 2, i64 2>
19; CHECK-NEXT:    [[TMP4:%.*]] = select i1 [[TOBOOL]], <2 x i64> [[TMP1]], <2 x i64> [[TMP3]]
20; CHECK-NEXT:    [[AND4:%.*]] = and i64 [[TMP2]], 2
21; CHECK-NEXT:    [[TOBOOL5:%.*]] = icmp eq i64 [[AND4]], 0
22; CHECK-NEXT:    [[TMP5:%.*]] = add nsw <2 x i64> [[TMP4]], <i64 1, i64 1>
23; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[TOBOOL5]], <2 x i64> [[TMP4]], <2 x i64> [[TMP5]]
24; CHECK-NEXT:    [[TMP6:%.*]] = xor i1 [[TOBOOL]], true
25; CHECK-NEXT:    [[TMP7:%.*]] = xor i1 [[TOBOOL5]], true
26; CHECK-NEXT:    [[TMP8:%.*]] = or i1 [[TMP6]], [[TMP7]]
27; CHECK-NEXT:    br i1 [[TMP8]], label [[TMP9:%.*]], label [[TMP10:%.*]]
28; CHECK:       9:
29; CHECK-NEXT:    store <2 x i64> [[SPEC_SELECT]], <2 x i64>* bitcast (i64* getelementptr inbounds ([[STRUCT_COUNTERS]], %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
30; CHECK-NEXT:    br label [[TMP10]]
31; CHECK:       10:
32; CHECK-NEXT:    ret i32 0
33;
34entry:
35  %0 = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
36  %1 = add nsw <2 x i64> %0, <i64 1, i64 1>
37  store <2 x i64> %1, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
38  %2 = load i64, i64* @m, align 8
39  %and = and i64 %2, 1
40  %tobool = icmp eq i64 %and, 0
41  br i1 %tobool, label %if.end, label %if.then
42
43if.then:                                          ; preds = %entry
44  %3 = add nsw <2 x i64> %0, <i64 2, i64 2>
45  store <2 x i64> %3, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
46  br label %if.end
47
48if.end:                                           ; preds = %entry, %if.then
49  %4 = phi <2 x i64> [ %1, %entry ], [ %3, %if.then ]
50  %and4 = and i64 %2, 2
51  %tobool5 = icmp eq i64 %and4, 0
52  br i1 %tobool5, label %if.end9, label %if.then6
53
54if.then6:                                         ; preds = %if.end
55  %5 = add nsw <2 x i64> %4, <i64 1, i64 1>
56  store <2 x i64> %5, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
57  br label %if.end9
58
59if.end9:                                          ; preds = %if.end, %if.then6
60  ret i32 0
61}
62
63define i32 @align_not_equal() local_unnamed_addr {
64; CHECK-LABEL: @align_not_equal(
65; CHECK-NEXT:  entry:
66; CHECK-NEXT:    [[TMP0:%.*]] = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds ([[STRUCT_COUNTERS:%.*]], %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
67; CHECK-NEXT:    [[TMP1:%.*]] = add nsw <2 x i64> [[TMP0]], <i64 1, i64 1>
68; CHECK-NEXT:    store <2 x i64> [[TMP1]], <2 x i64>* bitcast (i64* getelementptr inbounds ([[STRUCT_COUNTERS]], %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
69; CHECK-NEXT:    [[TMP2:%.*]] = load i64, i64* @m, align 8
70; CHECK-NEXT:    [[AND:%.*]] = and i64 [[TMP2]], 1
71; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i64 [[AND]], 0
72; CHECK-NEXT:    [[TMP3:%.*]] = add nsw <2 x i64> [[TMP0]], <i64 2, i64 2>
73; CHECK-NEXT:    [[TMP4:%.*]] = select i1 [[TOBOOL]], <2 x i64> [[TMP1]], <2 x i64> [[TMP3]]
74; CHECK-NEXT:    [[AND4:%.*]] = and i64 [[TMP2]], 2
75; CHECK-NEXT:    [[TOBOOL5:%.*]] = icmp eq i64 [[AND4]], 0
76; CHECK-NEXT:    [[TMP5:%.*]] = add nsw <2 x i64> [[TMP4]], <i64 1, i64 1>
77; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[TOBOOL5]], <2 x i64> [[TMP4]], <2 x i64> [[TMP5]]
78; CHECK-NEXT:    [[TMP6:%.*]] = xor i1 [[TOBOOL]], true
79; CHECK-NEXT:    [[TMP7:%.*]] = xor i1 [[TOBOOL5]], true
80; CHECK-NEXT:    [[TMP8:%.*]] = or i1 [[TMP6]], [[TMP7]]
81; CHECK-NEXT:    br i1 [[TMP8]], label [[TMP9:%.*]], label [[TMP10:%.*]]
82; CHECK:       9:
83; CHECK-NEXT:    store <2 x i64> [[SPEC_SELECT]], <2 x i64>* bitcast (i64* getelementptr inbounds ([[STRUCT_COUNTERS]], %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
84; CHECK-NEXT:    br label [[TMP10]]
85; CHECK:       10:
86; CHECK-NEXT:    ret i32 0
87;
88entry:
89  %0 = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
90  %1 = add nsw <2 x i64> %0, <i64 1, i64 1>
91  store <2 x i64> %1, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
92  %2 = load i64, i64* @m, align 8
93  %and = and i64 %2, 1
94  %tobool = icmp eq i64 %and, 0
95  br i1 %tobool, label %if.end, label %if.then
96
97if.then:                                          ; preds = %entry
98  %3 = add nsw <2 x i64> %0, <i64 2, i64 2>
99  store <2 x i64> %3, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 16
100  br label %if.end
101
102if.end:                                           ; preds = %entry, %if.then
103  %4 = phi <2 x i64> [ %1, %entry ], [ %3, %if.then ]
104  %and4 = and i64 %2, 2
105  %tobool5 = icmp eq i64 %and4, 0
106  br i1 %tobool5, label %if.end9, label %if.then6
107
108if.then6:                                         ; preds = %if.end
109  %5 = add nsw <2 x i64> %4, <i64 1, i64 1>
110  store <2 x i64> %5, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
111  br label %if.end9
112
113if.end9:                                          ; preds = %if.end, %if.then6
114  ret i32 0
115}
116
117define i32 @align_single_zero() local_unnamed_addr {
118; CHECK-LABEL: @align_single_zero(
119; CHECK-NEXT:  entry:
120; CHECK-NEXT:    [[TMP0:%.*]] = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds ([[STRUCT_COUNTERS:%.*]], %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
121; CHECK-NEXT:    [[TMP1:%.*]] = add nsw <2 x i64> [[TMP0]], <i64 1, i64 1>
122; CHECK-NEXT:    store <2 x i64> [[TMP1]], <2 x i64>* bitcast (i64* getelementptr inbounds ([[STRUCT_COUNTERS]], %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
123; CHECK-NEXT:    [[TMP2:%.*]] = load i64, i64* @m, align 8
124; CHECK-NEXT:    [[AND:%.*]] = and i64 [[TMP2]], 1
125; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i64 [[AND]], 0
126; CHECK-NEXT:    [[TMP3:%.*]] = add nsw <2 x i64> [[TMP0]], <i64 2, i64 2>
127; CHECK-NEXT:    [[TMP4:%.*]] = select i1 [[TOBOOL]], <2 x i64> [[TMP1]], <2 x i64> [[TMP3]]
128; CHECK-NEXT:    [[AND4:%.*]] = and i64 [[TMP2]], 2
129; CHECK-NEXT:    [[TOBOOL5:%.*]] = icmp eq i64 [[AND4]], 0
130; CHECK-NEXT:    [[TMP5:%.*]] = add nsw <2 x i64> [[TMP4]], <i64 1, i64 1>
131; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[TOBOOL5]], <2 x i64> [[TMP4]], <2 x i64> [[TMP5]]
132; CHECK-NEXT:    [[TMP6:%.*]] = xor i1 [[TOBOOL]], true
133; CHECK-NEXT:    [[TMP7:%.*]] = xor i1 [[TOBOOL5]], true
134; CHECK-NEXT:    [[TMP8:%.*]] = or i1 [[TMP6]], [[TMP7]]
135; CHECK-NEXT:    br i1 [[TMP8]], label [[TMP9:%.*]], label [[TMP10:%.*]]
136; CHECK:       9:
137; CHECK-NEXT:    store <2 x i64> [[SPEC_SELECT]], <2 x i64>* bitcast (i64* getelementptr inbounds ([[STRUCT_COUNTERS]], %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
138; CHECK-NEXT:    br label [[TMP10]]
139; CHECK:       10:
140; CHECK-NEXT:    ret i32 0
141;
142entry:
143  %0 = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
144  %1 = add nsw <2 x i64> %0, <i64 1, i64 1>
145  store <2 x i64> %1, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
146  %2 = load i64, i64* @m, align 8
147  %and = and i64 %2, 1
148  %tobool = icmp eq i64 %and, 0
149  br i1 %tobool, label %if.end, label %if.then
150
151if.then:                                          ; preds = %entry
152  %3 = add nsw <2 x i64> %0, <i64 2, i64 2>
153  store <2 x i64> %3, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*)
154  br label %if.end
155
156if.end:                                           ; preds = %entry, %if.then
157  %4 = phi <2 x i64> [ %1, %entry ], [ %3, %if.then ]
158  %and4 = and i64 %2, 2
159  %tobool5 = icmp eq i64 %and4, 0
160  br i1 %tobool5, label %if.end9, label %if.then6
161
162if.then6:                                         ; preds = %if.end
163  %5 = add nsw <2 x i64> %4, <i64 1, i64 1>
164  store <2 x i64> %5, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
165  br label %if.end9
166
167if.end9:                                          ; preds = %if.end, %if.then6
168  ret i32 0
169}
170
171define i32 @align_single_zero_second_greater_default() local_unnamed_addr {
172; CHECK-LABEL: @align_single_zero_second_greater_default(
173; CHECK-NEXT:  entry:
174; CHECK-NEXT:    [[TMP0:%.*]] = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds ([[STRUCT_COUNTERS:%.*]], %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
175; CHECK-NEXT:    [[TMP1:%.*]] = add nsw <2 x i64> [[TMP0]], <i64 1, i64 1>
176; CHECK-NEXT:    store <2 x i64> [[TMP1]], <2 x i64>* bitcast (i64* getelementptr inbounds ([[STRUCT_COUNTERS]], %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
177; CHECK-NEXT:    [[TMP2:%.*]] = load i64, i64* @m, align 8
178; CHECK-NEXT:    [[AND:%.*]] = and i64 [[TMP2]], 1
179; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i64 [[AND]], 0
180; CHECK-NEXT:    [[TMP3:%.*]] = add nsw <2 x i64> [[TMP0]], <i64 2, i64 2>
181; CHECK-NEXT:    [[TMP4:%.*]] = select i1 [[TOBOOL]], <2 x i64> [[TMP1]], <2 x i64> [[TMP3]]
182; CHECK-NEXT:    [[AND4:%.*]] = and i64 [[TMP2]], 2
183; CHECK-NEXT:    [[TOBOOL5:%.*]] = icmp eq i64 [[AND4]], 0
184; CHECK-NEXT:    [[TMP5:%.*]] = add nsw <2 x i64> [[TMP4]], <i64 1, i64 1>
185; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[TOBOOL5]], <2 x i64> [[TMP4]], <2 x i64> [[TMP5]]
186; CHECK-NEXT:    [[TMP6:%.*]] = xor i1 [[TOBOOL]], true
187; CHECK-NEXT:    [[TMP7:%.*]] = xor i1 [[TOBOOL5]], true
188; CHECK-NEXT:    [[TMP8:%.*]] = or i1 [[TMP6]], [[TMP7]]
189; CHECK-NEXT:    br i1 [[TMP8]], label [[TMP9:%.*]], label [[TMP10:%.*]]
190; CHECK:       9:
191; CHECK-NEXT:    store <2 x i64> [[SPEC_SELECT]], <2 x i64>* bitcast (i64* getelementptr inbounds ([[STRUCT_COUNTERS]], %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 16
192; CHECK-NEXT:    br label [[TMP10]]
193; CHECK:       10:
194; CHECK-NEXT:    ret i32 0
195;
196entry:
197  %0 = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
198  %1 = add nsw <2 x i64> %0, <i64 1, i64 1>
199  store <2 x i64> %1, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
200  %2 = load i64, i64* @m, align 8
201  %and = and i64 %2, 1
202  %tobool = icmp eq i64 %and, 0
203  br i1 %tobool, label %if.end, label %if.then
204
205if.then:                                          ; preds = %entry
206  %3 = add nsw <2 x i64> %0, <i64 2, i64 2>
207  store <2 x i64> %3, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 32
208  br label %if.end
209
210if.end:                                           ; preds = %entry, %if.then
211  %4 = phi <2 x i64> [ %1, %entry ], [ %3, %if.then ]
212  %and4 = and i64 %2, 2
213  %tobool5 = icmp eq i64 %and4, 0
214  br i1 %tobool5, label %if.end9, label %if.then6
215
216if.then6:                                         ; preds = %if.end
217  %5 = add nsw <2 x i64> %4, <i64 1, i64 1>
218  store <2 x i64> %5, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*)
219  br label %if.end9
220
221if.end9:                                          ; preds = %if.end, %if.then6
222  ret i32 0
223}
224
225define i32 @align_both_zero() local_unnamed_addr {
226; CHECK-LABEL: @align_both_zero(
227; CHECK-NEXT:  entry:
228; CHECK-NEXT:    [[TMP0:%.*]] = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds ([[STRUCT_COUNTERS:%.*]], %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
229; CHECK-NEXT:    [[TMP1:%.*]] = add nsw <2 x i64> [[TMP0]], <i64 1, i64 1>
230; CHECK-NEXT:    store <2 x i64> [[TMP1]], <2 x i64>* bitcast (i64* getelementptr inbounds ([[STRUCT_COUNTERS]], %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
231; CHECK-NEXT:    [[TMP2:%.*]] = load i64, i64* @m, align 8
232; CHECK-NEXT:    [[AND:%.*]] = and i64 [[TMP2]], 1
233; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i64 [[AND]], 0
234; CHECK-NEXT:    [[TMP3:%.*]] = add nsw <2 x i64> [[TMP0]], <i64 2, i64 2>
235; CHECK-NEXT:    [[TMP4:%.*]] = select i1 [[TOBOOL]], <2 x i64> [[TMP1]], <2 x i64> [[TMP3]]
236; CHECK-NEXT:    [[AND4:%.*]] = and i64 [[TMP2]], 2
237; CHECK-NEXT:    [[TOBOOL5:%.*]] = icmp eq i64 [[AND4]], 0
238; CHECK-NEXT:    [[TMP5:%.*]] = add nsw <2 x i64> [[TMP4]], <i64 1, i64 1>
239; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[TOBOOL5]], <2 x i64> [[TMP4]], <2 x i64> [[TMP5]]
240; CHECK-NEXT:    [[TMP6:%.*]] = xor i1 [[TOBOOL]], true
241; CHECK-NEXT:    [[TMP7:%.*]] = xor i1 [[TOBOOL5]], true
242; CHECK-NEXT:    [[TMP8:%.*]] = or i1 [[TMP6]], [[TMP7]]
243; CHECK-NEXT:    br i1 [[TMP8]], label [[TMP9:%.*]], label [[TMP10:%.*]]
244; CHECK:       9:
245; CHECK-NEXT:    store <2 x i64> [[SPEC_SELECT]], <2 x i64>* bitcast (i64* getelementptr inbounds ([[STRUCT_COUNTERS]], %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 16
246; CHECK-NEXT:    br label [[TMP10]]
247; CHECK:       10:
248; CHECK-NEXT:    ret i32 0
249;
250entry:
251  %0 = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
252  %1 = add nsw <2 x i64> %0, <i64 1, i64 1>
253  store <2 x i64> %1, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
254  %2 = load i64, i64* @m, align 8
255  %and = and i64 %2, 1
256  %tobool = icmp eq i64 %and, 0
257  br i1 %tobool, label %if.end, label %if.then
258
259if.then:                                          ; preds = %entry
260  %3 = add nsw <2 x i64> %0, <i64 2, i64 2>
261  store <2 x i64> %3, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*)
262  br label %if.end
263
264if.end:                                           ; preds = %entry, %if.then
265  %4 = phi <2 x i64> [ %1, %entry ], [ %3, %if.then ]
266  %and4 = and i64 %2, 2
267  %tobool5 = icmp eq i64 %and4, 0
268  br i1 %tobool5, label %if.end9, label %if.then6
269
270if.then6:                                         ; preds = %if.end
271  %5 = add nsw <2 x i64> %4, <i64 1, i64 1>
272  store <2 x i64> %5, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*)
273  br label %if.end9
274
275if.end9:                                          ; preds = %if.end, %if.then6
276  ret i32 0
277}
278