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