1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -irce < %s -S | FileCheck %s
3
4; REQUIRES: asserts
5
6; IRCE creates the pre and post loop, and invokes the
7; canonicalizing these loops to LCSSA and loop-simplfy structure. Make sure that the update to the loopinfo does not
8; incorrectly change the header while canonicalizing these pre/post loops. We
9; were incorrectly updating LI when the split loop is a subloop as in the case below.
10source_filename = "correct-loop-info.ll"
11
12define void @baz() personality i32* ()* @ham {
13; CHECK-LABEL: @baz(
14; CHECK-NEXT:  bb:
15; CHECK-NEXT:    br label [[OUTERHEADER:%.*]]
16; CHECK:       outerheader:
17; CHECK-NEXT:    [[TMP:%.*]] = icmp slt i32 undef, 84
18; CHECK-NEXT:    br i1 [[TMP]], label [[BB2:%.*]], label [[BB16:%.*]]
19; CHECK:       bb2:
20; CHECK-NEXT:    br i1 false, label [[INNERHEADER_PRELOOP_PREHEADER:%.*]], label [[PRELOOP_PSEUDO_EXIT:%.*]]
21; CHECK:       innerheader.preloop.preheader:
22; CHECK-NEXT:    br label [[INNERHEADER_PRELOOP:%.*]]
23; CHECK:       mainloop:
24; CHECK-NEXT:    [[TMP0:%.*]] = icmp slt i32 [[INDVAR_END:%.*]], 0
25; CHECK-NEXT:    br i1 [[TMP0]], label [[INNERHEADER_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
26; CHECK:       innerheader.preheader:
27; CHECK-NEXT:    br label [[INNERHEADER:%.*]]
28; CHECK:       innerheader:
29; CHECK-NEXT:    [[TMP4:%.*]] = phi i32 [ [[TMP6:%.*]], [[BB8:%.*]] ], [ [[TMP4_PRELOOP_COPY:%.*]], [[INNERHEADER_PREHEADER]] ]
30; CHECK-NEXT:    invoke void @pluto()
31; CHECK-NEXT:    to label [[BB5:%.*]] unwind label %outer_exiting.loopexit.split-lp.loopexit.split-lp
32; CHECK:       bb5:
33; CHECK-NEXT:    [[TMP6]] = add i32 [[TMP4]], 1
34; CHECK-NEXT:    [[TMP7:%.*]] = icmp slt i32 [[TMP6]], 1
35; CHECK-NEXT:    br i1 true, label [[BB8]], label [[EXIT3_LOOPEXIT5:%.*]]
36; CHECK:       bb8:
37; CHECK-NEXT:    [[TMP9:%.*]] = icmp slt i32 [[TMP6]], 84
38; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i32 [[TMP6]], 0
39; CHECK-NEXT:    br i1 [[TMP1]], label [[INNERHEADER]], label [[MAIN_EXIT_SELECTOR:%.*]]
40; CHECK:       main.exit.selector:
41; CHECK-NEXT:    [[TMP6_LCSSA:%.*]] = phi i32 [ [[TMP6]], [[BB8]] ]
42; CHECK-NEXT:    [[TMP2:%.*]] = icmp slt i32 [[TMP6_LCSSA]], 84
43; CHECK-NEXT:    br i1 [[TMP2]], label [[MAIN_PSEUDO_EXIT]], label [[BB13:%.*]]
44; CHECK:       main.pseudo.exit:
45; CHECK-NEXT:    [[TMP4_COPY:%.*]] = phi i32 [ [[TMP4_PRELOOP_COPY]], [[MAINLOOP:%.*]] ], [ [[TMP6_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
46; CHECK-NEXT:    [[INDVAR_END1:%.*]] = phi i32 [ [[INDVAR_END]], [[MAINLOOP]] ], [ [[TMP6_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
47; CHECK-NEXT:    br label [[POSTLOOP:%.*]]
48; CHECK:       outer_exiting.loopexit:
49; CHECK-NEXT:    [[LPAD_LOOPEXIT:%.*]] = landingpad { i8*, i32 }
50; CHECK-NEXT:    cleanup
51; CHECK-NEXT:    br label [[OUTER_EXITING:%.*]]
52; CHECK:       outer_exiting.loopexit.split-lp.loopexit:
53; CHECK-NEXT:    [[LPAD_LOOPEXIT2:%.*]] = landingpad { i8*, i32 }
54; CHECK-NEXT:    cleanup
55; CHECK-NEXT:    br label %outer_exiting.loopexit.split-lp
56; CHECK:       outer_exiting.loopexit.split-lp.loopexit.split-lp:
57; CHECK-NEXT:    %lpad.loopexit.split-lp3 = landingpad { i8*, i32 }
58; CHECK-NEXT:    cleanup
59; CHECK-NEXT:    br label %outer_exiting.loopexit.split-lp
60; CHECK:       outer_exiting.loopexit.split-lp:
61; CHECK-NEXT:    br label [[OUTER_EXITING]]
62; CHECK:       outer_exiting:
63; CHECK-NEXT:    switch i32 undef, label [[EXIT2:%.*]] [
64; CHECK-NEXT:    i32 142, label [[BB14:%.*]]
65; CHECK-NEXT:    i32 448, label [[EXIT:%.*]]
66; CHECK-NEXT:    ]
67; CHECK:       exit3.loopexit:
68; CHECK-NEXT:    br label [[EXIT3:%.*]]
69; CHECK:       exit3.loopexit4:
70; CHECK-NEXT:    br label [[EXIT3]]
71; CHECK:       exit3.loopexit5:
72; CHECK-NEXT:    br label [[EXIT3]]
73; CHECK:       exit3:
74; CHECK-NEXT:    ret void
75; CHECK:       bb13.loopexit:
76; CHECK-NEXT:    br label [[BB13]]
77; CHECK:       bb13:
78; CHECK-NEXT:    unreachable
79; CHECK:       bb14:
80; CHECK-NEXT:    br label [[OUTERHEADER]]
81; CHECK:       exit:
82; CHECK-NEXT:    ret void
83; CHECK:       bb16:
84; CHECK-NEXT:    ret void
85; CHECK:       exit2:
86; CHECK-NEXT:    ret void
87; CHECK:       innerheader.preloop:
88; CHECK-NEXT:    [[TMP4_PRELOOP:%.*]] = phi i32 [ [[TMP6_PRELOOP:%.*]], [[BB8_PRELOOP:%.*]] ], [ undef, [[INNERHEADER_PRELOOP_PREHEADER]] ]
89; CHECK-NEXT:    invoke void @pluto()
90; CHECK-NEXT:    to label [[BB5_PRELOOP:%.*]] unwind label [[OUTER_EXITING_LOOPEXIT:%.*]]
91; CHECK:       bb5.preloop:
92; CHECK-NEXT:    [[TMP6_PRELOOP]] = add i32 [[TMP4_PRELOOP]], 1
93; CHECK-NEXT:    [[TMP7_PRELOOP:%.*]] = icmp slt i32 [[TMP6_PRELOOP]], 1
94; CHECK-NEXT:    br i1 [[TMP7_PRELOOP]], label [[BB8_PRELOOP]], label [[EXIT3_LOOPEXIT:%.*]]
95; CHECK:       bb8.preloop:
96; CHECK-NEXT:    [[TMP9_PRELOOP:%.*]] = icmp slt i32 [[TMP6_PRELOOP]], 84
97; CHECK-NEXT:    [[TMP3:%.*]] = icmp slt i32 [[TMP6_PRELOOP]], -1
98; CHECK-NEXT:    br i1 [[TMP3]], label [[INNERHEADER_PRELOOP]], label [[PRELOOP_EXIT_SELECTOR:%.*]], !llvm.loop !0, !irce.loop.clone !5
99; CHECK:       preloop.exit.selector:
100; CHECK-NEXT:    [[TMP6_PRELOOP_LCSSA:%.*]] = phi i32 [ [[TMP6_PRELOOP]], [[BB8_PRELOOP]] ]
101; CHECK-NEXT:    [[TMP4:%.*]] = icmp slt i32 [[TMP6_PRELOOP_LCSSA]], 84
102; CHECK-NEXT:    br i1 [[TMP4]], label [[PRELOOP_PSEUDO_EXIT]], label [[BB13]]
103; CHECK:       preloop.pseudo.exit:
104; CHECK-NEXT:    [[TMP4_PRELOOP_COPY]] = phi i32 [ undef, [[BB2]] ], [ [[TMP6_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]
105; CHECK-NEXT:    [[INDVAR_END]] = phi i32 [ undef, [[BB2]] ], [ [[TMP6_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]
106; CHECK-NEXT:    br label [[MAINLOOP]]
107; CHECK:       postloop:
108; CHECK-NEXT:    br label [[INNERHEADER_POSTLOOP:%.*]]
109; CHECK:       innerheader.postloop:
110; CHECK-NEXT:    [[TMP4_POSTLOOP:%.*]] = phi i32 [ [[TMP6_POSTLOOP:%.*]], [[BB8_POSTLOOP:%.*]] ], [ [[TMP4_COPY]], [[POSTLOOP]] ]
111; CHECK-NEXT:    invoke void @pluto()
112; CHECK-NEXT:    to label [[BB5_POSTLOOP:%.*]] unwind label %outer_exiting.loopexit.split-lp.loopexit
113; CHECK:       bb5.postloop:
114; CHECK-NEXT:    [[TMP6_POSTLOOP]] = add i32 [[TMP4_POSTLOOP]], 1
115; CHECK-NEXT:    [[TMP7_POSTLOOP:%.*]] = icmp slt i32 [[TMP6_POSTLOOP]], 1
116; CHECK-NEXT:    br i1 [[TMP7_POSTLOOP]], label [[BB8_POSTLOOP]], label [[EXIT3_LOOPEXIT4:%.*]]
117; CHECK:       bb8.postloop:
118; CHECK-NEXT:    [[TMP9_POSTLOOP:%.*]] = icmp slt i32 [[TMP6_POSTLOOP]], 84
119; CHECK-NEXT:    br i1 [[TMP9_POSTLOOP]], label [[INNERHEADER_POSTLOOP]], label [[BB13_LOOPEXIT:%.*]], !llvm.loop !6, !irce.loop.clone !5
120;
121bb:
122  br label %outerheader
123
124outerheader:                                              ; preds = %bb14, %bb
125  %tmp = icmp slt i32 undef, 84
126  br i1 %tmp, label %bb2, label %bb16
127
128bb2:                                              ; preds = %outerheader
129  br label %innerheader
130
131innerheader:                                              ; preds = %bb8, %bb2
132  %tmp4 = phi i32 [ %tmp6, %bb8 ], [ undef, %bb2 ]
133  invoke void @pluto()
134  to label %bb5 unwind label %outer_exiting
135
136bb5:                                              ; preds = %innerheader
137  %tmp6 = add i32 %tmp4, 1
138  %tmp7 = icmp slt i32 %tmp6, 1
139  br i1 %tmp7, label %bb8, label %exit3
140
141bb8:                                              ; preds = %bb5
142  %tmp9 = icmp slt i32 %tmp6, 84
143  br i1 %tmp9, label %innerheader, label %bb13
144
145outer_exiting:                                             ; preds = %innerheader
146  %tmp11 = landingpad { i8*, i32 }
147  cleanup
148  switch i32 undef, label %exit2 [
149  i32 142, label %bb14
150  i32 448, label %exit
151  ]
152
153exit3:                                             ; preds = %bb5
154  ret void
155
156bb13:                                             ; preds = %bb8
157  unreachable
158
159bb14:                                             ; preds = %outer_exiting
160  br label %outerheader
161
162exit:                                             ; preds = %outer_exiting
163  ret void
164
165bb16:                                             ; preds = %outerheader
166  ret void
167
168exit2:                                             ; preds = %outer_exiting
169  ret void
170}
171
172declare i32* @ham()
173
174declare void @pluto()
175
176!0 = distinct !{!0, !1, !2, !3, !4}
177!1 = !{!"llvm.loop.unroll.disable"}
178!2 = !{!"llvm.loop.vectorize.enable", i1 false}
179!3 = !{!"llvm.loop.licm_versioning.disable"}
180!4 = !{!"llvm.loop.distribute.enable", i1 false}
181!5 = !{}
182!6 = distinct !{!6, !1, !2, !3, !4}
183