1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes='loop(loop-interchange),loop-mssa(simple-loop-unswitch<nontrivial>)' -S -verify-scev %s | FileCheck %s
3
4declare void @clobber()
5
6; Make sure SCEV loop and block dispositions are properly invalidated after
7; unswitching.
8define void @test_pr58564(i16 %a, i1 %c.1, ptr %dst) {
9; CHECK-LABEL: @test_pr58564(
10; CHECK-NEXT:  entry:
11; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i16 [[A:%.*]], -6
12; CHECK-NEXT:    br i1 [[TMP0]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
13; CHECK:       entry.split.us:
14; CHECK-NEXT:    br i1 [[C_1:%.*]], label [[ENTRY_SPLIT_US_SPLIT_US:%.*]], label [[ENTRY_SPLIT_US_SPLIT:%.*]]
15; CHECK:       entry.split.us.split.us:
16; CHECK-NEXT:    br label [[LOOP_1_HEADER_US_US:%.*]]
17; CHECK:       loop.1.header.us.us:
18; CHECK-NEXT:    br label [[LOOP_1_HEADER_SPLIT_US_US_US:%.*]]
19; CHECK:       loop.1.header.split.us.us.us:
20; CHECK-NEXT:    br label [[LOOP_1_HEADER_SPLIT_US_SPLIT_US_SPLIT_US_SPLIT_US:%.*]]
21; CHECK:       loop.1.header.split.us.split.us.split.us.split.us:
22; CHECK-NEXT:    br label [[LOOP_1_HEADER_SPLIT_US_SPLIT_US_SPLIT_US:%.*]]
23; CHECK:       entry.split.us.split:
24; CHECK-NEXT:    br label [[LOOP_1_HEADER_US:%.*]]
25; CHECK:       loop.1.header.us:
26; CHECK-NEXT:    br label [[LOOP_1_HEADER_SPLIT_US_US:%.*]]
27; CHECK:       loop.4.header.us5:
28; CHECK-NEXT:    br label [[LOOP_5_US6:%.*]]
29; CHECK:       loop.5.us6:
30; CHECK-NEXT:    [[IV_US7:%.*]] = phi i16 [ 0, [[LOOP_4_HEADER_US5:%.*]] ], [ [[IV_NEXT_US9:%.*]], [[LOOP_5_US6]] ]
31; CHECK-NEXT:    [[GEP_US8:%.*]] = getelementptr inbounds ptr, ptr [[DST:%.*]], i16 [[IV_US7]]
32; CHECK-NEXT:    store ptr null, ptr [[GEP_US8]], align 8
33; CHECK-NEXT:    [[IV_NEXT_US9]] = add nuw nsw i16 [[IV_US7]], 1
34; CHECK-NEXT:    [[EC_US10:%.*]] = icmp ne i16 [[IV_US7]], 10000
35; CHECK-NEXT:    br i1 [[EC_US10]], label [[LOOP_5_US6]], label [[LOOP_4_LATCH_US11:%.*]]
36; CHECK:       loop.4.latch.us11:
37; CHECK-NEXT:    br label [[LOOP_1_LATCH_US:%.*]]
38; CHECK:       loop.1.latch.us:
39; CHECK-NEXT:    br label [[LOOP_1_HEADER_US]]
40; CHECK:       loop.4.header.preheader.us:
41; CHECK-NEXT:    br i1 false, label [[LOOP_4_HEADER_PREHEADER_SPLIT4_US_SPLIT_US:%.*]], label [[LOOP_4_HEADER_PREHEADER_SPLIT4_US15:%.*]]
42; CHECK:       loop.1.header.split.us.us:
43; CHECK-NEXT:    br label [[LOOP_1_HEADER_SPLIT_US_SPLIT_US14:%.*]]
44; CHECK:       loop.2.header.us.us12:
45; CHECK-NEXT:    br label [[LOOP_2_HEADER_SPLIT_US_US_US13:%.*]]
46; CHECK:       loop.2.latch.us.us:
47; CHECK-NEXT:    br i1 false, label [[LOOP_2_HEADER_US_US12:%.*]], label [[LOOP_4_HEADER_PREHEADER_SPLIT_US_US:%.*]]
48; CHECK:       loop.2.header.split.us.us.us13:
49; CHECK-NEXT:    br label [[LOOP_2_HEADER_SPLIT_US_SPLIT_US3_US:%.*]]
50; CHECK:       loop.3.header.us.us1.us:
51; CHECK-NEXT:    br label [[LOOP_3_LATCH_US_US2_US:%.*]]
52; CHECK:       loop.3.latch.us.us2.us:
53; CHECK-NEXT:    br label [[LOOP_2_LATCH_SPLIT_US_US_US:%.*]]
54; CHECK:       loop.2.latch.split.us.us.us:
55; CHECK-NEXT:    br label [[LOOP_2_LATCH_US_US:%.*]]
56; CHECK:       loop.2.header.split.us.split.us3.us:
57; CHECK-NEXT:    br label [[LOOP_3_HEADER_US_US1_US:%.*]]
58; CHECK:       loop.4.header.preheader.split.us.us:
59; CHECK-NEXT:    br label [[LOOP_4_HEADER_PREHEADER_US:%.*]]
60; CHECK:       loop.1.header.split.us.split.us14:
61; CHECK-NEXT:    br label [[LOOP_2_HEADER_US_US12]]
62; CHECK:       loop.4.header.preheader.split4.us15:
63; CHECK-NEXT:    br label [[LOOP_4_HEADER_US5]]
64; CHECK:       loop.4.header.preheader.split4.us.split.us:
65; CHECK-NEXT:    br label [[LOOP_4_HEADER_PREHEADER_SPLIT4_US:%.*]]
66; CHECK:       loop.1.header.split.us.split.us.split.us:
67; CHECK-NEXT:    br label [[LOOP_1_HEADER_SPLIT_US_SPLIT_US:%.*]]
68; CHECK:       entry.split:
69; CHECK-NEXT:    br label [[LOOP_1_HEADER:%.*]]
70; CHECK:       loop.1.header:
71; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i16 [[A]], -6
72; CHECK-NEXT:    br i1 [[TMP1]], label [[LOOP_1_HEADER_SPLIT_US:%.*]], label [[LOOP_1_HEADER_SPLIT:%.*]]
73; CHECK:       loop.1.header.split.us:
74; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_1_HEADER_SPLIT_US_SPLIT_US_SPLIT:%.*]], label [[LOOP_1_HEADER_SPLIT_US_SPLIT:%.*]]
75; CHECK:       loop.1.header.split.us.split.us.split:
76; CHECK-NEXT:    br label [[LOOP_1_HEADER_SPLIT_US_SPLIT_US]]
77; CHECK:       loop.1.header.split.us.split.us:
78; CHECK-NEXT:    br label [[LOOP_2_HEADER_US_US:%.*]]
79; CHECK:       loop.2.header.us.us:
80; CHECK-NEXT:    br label [[LOOP_2_HEADER_SPLIT_US_US_US:%.*]]
81; CHECK:       loop.2.header.split.us.us.us:
82; CHECK-NEXT:    br label [[LOOP_2_HEADER_SPLIT_US_SPLIT_US_SPLIT_US_SPLIT_US:%.*]]
83; CHECK:       loop.2.header.split.us.split.us.split.us.split.us:
84; CHECK-NEXT:    br label [[LOOP_2_HEADER_SPLIT_US_SPLIT_US_SPLIT_US:%.*]]
85; CHECK:       loop.1.header.split.us.split:
86; CHECK-NEXT:    br label [[LOOP_2_HEADER_US:%.*]]
87; CHECK:       loop.2.header.us:
88; CHECK-NEXT:    br label [[LOOP_2_HEADER_SPLIT_US_US:%.*]]
89; CHECK:       loop.2.latch.us:
90; CHECK-NEXT:    br i1 false, label [[LOOP_2_HEADER_US]], label [[LOOP_4_HEADER_PREHEADER_SPLIT_US:%.*]]
91; CHECK:       loop.2.header.split.us.us:
92; CHECK-NEXT:    br label [[LOOP_2_HEADER_SPLIT_US_SPLIT_US3:%.*]]
93; CHECK:       loop.3.header.us.us1:
94; CHECK-NEXT:    br label [[LOOP_3_LATCH_US_US2:%.*]]
95; CHECK:       loop.3.latch.us.us2:
96; CHECK-NEXT:    br label [[LOOP_2_LATCH_SPLIT_US_US:%.*]]
97; CHECK:       loop.2.latch.split.us.us:
98; CHECK-NEXT:    br label [[LOOP_2_LATCH_US:%.*]]
99; CHECK:       loop.2.header.split.us.split.us3:
100; CHECK-NEXT:    br label [[LOOP_3_HEADER_US_US1:%.*]]
101; CHECK:       loop.4.header.preheader.split.us:
102; CHECK-NEXT:    br label [[LOOP_4_HEADER_PREHEADER:%.*]]
103; CHECK:       loop.2.header.split.us.split.us.split.us:
104; CHECK-NEXT:    br label [[LOOP_2_HEADER_SPLIT_US_SPLIT_US:%.*]]
105; CHECK:       loop.1.header.split:
106; CHECK-NEXT:    br label [[LOOP_2_HEADER:%.*]]
107; CHECK:       loop.2.header:
108; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i16 [[A]], -6
109; CHECK-NEXT:    br i1 [[TMP2]], label [[LOOP_2_HEADER_SPLIT_US:%.*]], label [[LOOP_2_HEADER_SPLIT:%.*]]
110; CHECK:       loop.2.header.split.us:
111; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_2_HEADER_SPLIT_US_SPLIT_US_SPLIT:%.*]], label [[LOOP_2_HEADER_SPLIT_US_SPLIT:%.*]]
112; CHECK:       loop.2.header.split.us.split.us.split:
113; CHECK-NEXT:    br label [[LOOP_2_HEADER_SPLIT_US_SPLIT_US]]
114; CHECK:       loop.2.header.split.us.split.us:
115; CHECK-NEXT:    br label [[LOOP_3_HEADER_US_US:%.*]]
116; CHECK:       loop.3.header.us.us:
117; CHECK-NEXT:    br label [[LOOP_3_LATCH_US_US:%.*]]
118; CHECK:       loop.3.latch.us.us:
119; CHECK-NEXT:    br label [[LOOP_3_HEADER_US_US]]
120; CHECK:       loop.2.header.split.us.split:
121; CHECK-NEXT:    br label [[LOOP_3_HEADER_US:%.*]]
122; CHECK:       loop.3.header.us:
123; CHECK-NEXT:    br label [[LOOP_3_LATCH_US:%.*]]
124; CHECK:       loop.3.latch.us:
125; CHECK-NEXT:    br label [[LOOP_2_LATCH_SPLIT_US:%.*]]
126; CHECK:       loop.2.latch.split.us:
127; CHECK-NEXT:    br label [[LOOP_2_LATCH:%.*]]
128; CHECK:       loop.2.header.split:
129; CHECK-NEXT:    br label [[LOOP_3_HEADER:%.*]]
130; CHECK:       loop.3.header:
131; CHECK-NEXT:    [[TMP3:%.*]] = icmp ult i16 [[A]], -6
132; CHECK-NEXT:    br i1 [[TMP3]], label [[LOOP_3_LATCH:%.*]], label [[LOOP_3_THEN:%.*]]
133; CHECK:       loop.3.then:
134; CHECK-NEXT:    call void @clobber()
135; CHECK-NEXT:    br label [[LOOP_3_LATCH]]
136; CHECK:       loop.3.latch:
137; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_3_HEADER]], label [[LOOP_2_LATCH_SPLIT:%.*]], !llvm.loop [[LOOP0:![0-9]+]]
138; CHECK:       loop.2.latch.split:
139; CHECK-NEXT:    br label [[LOOP_2_LATCH]]
140; CHECK:       loop.2.latch:
141; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_2_HEADER]], label [[LOOP_4_HEADER_PREHEADER_SPLIT:%.*]], !llvm.loop [[LOOP2:![0-9]+]]
142; CHECK:       loop.4.header.preheader.split:
143; CHECK-NEXT:    br label [[LOOP_4_HEADER_PREHEADER]]
144; CHECK:       loop.4.header.preheader:
145; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_4_HEADER_PREHEADER_SPLIT4_US_SPLIT:%.*]], label [[LOOP_4_HEADER_PREHEADER_SPLIT4:%.*]]
146; CHECK:       loop.4.header.preheader.split4.us.split:
147; CHECK-NEXT:    br label [[LOOP_4_HEADER_PREHEADER_SPLIT4_US]]
148; CHECK:       loop.4.header.preheader.split4.us:
149; CHECK-NEXT:    br label [[LOOP_4_HEADER_US:%.*]]
150; CHECK:       loop.4.header.us:
151; CHECK-NEXT:    br label [[LOOP_5_US:%.*]]
152; CHECK:       loop.5.us:
153; CHECK-NEXT:    [[IV_US:%.*]] = phi i16 [ 0, [[LOOP_4_HEADER_US]] ], [ [[IV_NEXT_US:%.*]], [[LOOP_5_US]] ]
154; CHECK-NEXT:    [[GEP_US:%.*]] = getelementptr inbounds ptr, ptr [[DST]], i16 [[IV_US]]
155; CHECK-NEXT:    store ptr null, ptr [[GEP_US]], align 8
156; CHECK-NEXT:    [[IV_NEXT_US]] = add nuw nsw i16 [[IV_US]], 1
157; CHECK-NEXT:    [[EC_US:%.*]] = icmp ne i16 [[IV_US]], 10000
158; CHECK-NEXT:    br i1 [[EC_US]], label [[LOOP_5_US]], label [[LOOP_4_LATCH_US:%.*]]
159; CHECK:       loop.4.latch.us:
160; CHECK-NEXT:    br label [[LOOP_4_HEADER_US]]
161; CHECK:       loop.4.header.preheader.split4:
162; CHECK-NEXT:    br label [[LOOP_4_HEADER:%.*]]
163; CHECK:       loop.4.header:
164; CHECK-NEXT:    br label [[LOOP_5:%.*]]
165; CHECK:       loop.5:
166; CHECK-NEXT:    [[IV:%.*]] = phi i16 [ 0, [[LOOP_4_HEADER]] ], [ [[IV_NEXT:%.*]], [[LOOP_5]] ]
167; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds ptr, ptr [[DST]], i16 [[IV]]
168; CHECK-NEXT:    store ptr null, ptr [[GEP]], align 8
169; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i16 [[IV]], 1
170; CHECK-NEXT:    [[EC:%.*]] = icmp ne i16 [[IV]], 10000
171; CHECK-NEXT:    br i1 [[EC]], label [[LOOP_5]], label [[LOOP_4_LATCH:%.*]]
172; CHECK:       loop.4.latch:
173; CHECK-NEXT:    br label [[LOOP_1_LATCH:%.*]]
174; CHECK:       loop.1.latch:
175; CHECK-NEXT:    br label [[LOOP_1_HEADER]], !llvm.loop [[LOOP3:![0-9]+]]
176;
177entry:
178  br label %loop.1.header
179
180loop.1.header:
181  br label %loop.2.header
182
183loop.2.header:
184  br label %loop.3.header
185
186loop.3.header:
187  %0 = icmp ult i16 %a, -6
188  br i1 %0, label %loop.3.latch, label %loop.3.then
189
190loop.3.then:
191  call void @clobber()
192  br label %loop.3.latch
193
194loop.3.latch:
195  br i1 %c.1, label %loop.3.header, label %loop.2.latch
196
197loop.2.latch:
198  br i1 %c.1, label %loop.2.header, label %loop.4.header
199
200loop.4.header:
201  br label %loop.5
202
203loop.5:
204  %iv = phi i16 [ 0, %loop.4.header ], [ %iv.next, %loop.5 ]
205  %gep = getelementptr inbounds ptr, ptr %dst, i16 %iv
206  store ptr null, ptr %gep, align 8
207  %iv.next = add nuw nsw i16 %iv, 1
208  %ec = icmp ne i16 %iv, 10000
209  br i1 %ec, label %loop.5, label %loop.4.latch
210
211loop.4.latch:
212  br i1 %c.1, label %loop.4.header, label %loop.1.latch
213
214loop.1.latch:
215  br label %loop.1.header
216}
217