1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; Check that phi analysis can determine the number of iterations of the
3 ; loop to peel such that the phi nodes (other than the iteration variable)
4 ; have their resulting values known and are thus removed by peeling the loop
5 ; at least that many times.
7 ; RUN: opt < %s -S -passes=loop-unroll | FileCheck %s
8 ; RUN: opt < %s -S -passes=loop-unroll-full | FileCheck %s
12 declare void @_Z1ff(float)
13 declare void @_Z1gi(i32 signext)
15 ; Check that phi analysis can handle a cast.
16 define void @_Z8castTestv() {
17 ; The phis become invariant through the chain of phis, with a unary
18 ; instruction on a loop invariant. Check that the phis for x, a, and y
19 ; are removed since x is based on a cast of y, which is based on a, which is
20 ; set on the backedge.
21 ; Consider the calls to g and f.
22 ; First iteration: g(0), x=0, f(0.0), y=0.0, a=5.0
23 ; Second iteration: g(0), x=0, f(0.0), y=5.0, a=5.0
24 ; Third iteration: g(0), x=5 (requires cast), f(5.0), a=5.0
25 ; Fourth iteration (and subsequent): g(5), x=5, f(5.0), a=5.0
26 ; Therefore, peeling 3 times removes the phi nodes, so check for 3 peels.
32 ; for(int i = 0; i <100000; ++i) {
41 ; CHECK-LABEL: @_Z8castTestv(
43 ; CHECK-NEXT: br label [[FOR_BODY_PEEL_BEGIN:%.*]]
44 ; CHECK: for.body.peel.begin:
45 ; CHECK-NEXT: br label [[FOR_BODY_PEEL:%.*]]
46 ; CHECK: for.body.peel:
47 ; CHECK-NEXT: tail call void @_Z1gi(i32 noundef signext 0)
48 ; CHECK-NEXT: [[CONV_PEEL:%.*]] = fptosi float 0.000000e+00 to i32
49 ; CHECK-NEXT: tail call void @_Z1ff(float noundef 0.000000e+00)
50 ; CHECK-NEXT: [[INC_PEEL:%.*]] = add nuw nsw i32 0, 1
51 ; CHECK-NEXT: [[EXITCOND_PEEL:%.*]] = icmp ne i32 [[INC_PEEL]], 100000
52 ; CHECK-NEXT: br i1 [[EXITCOND_PEEL]], label [[FOR_BODY_PEEL_NEXT:%.*]], label [[FOR_COND_CLEANUP:%.*]]
53 ; CHECK: for.body.peel.next:
54 ; CHECK-NEXT: br label [[FOR_BODY_PEEL2:%.*]]
55 ; CHECK: for.body.peel2:
56 ; CHECK-NEXT: tail call void @_Z1gi(i32 noundef signext [[CONV_PEEL]])
57 ; CHECK-NEXT: [[CONV_PEEL3:%.*]] = fptosi float 0.000000e+00 to i32
58 ; CHECK-NEXT: tail call void @_Z1ff(float noundef 0.000000e+00)
59 ; CHECK-NEXT: [[INC_PEEL4:%.*]] = add nuw nsw i32 [[INC_PEEL]], 1
60 ; CHECK-NEXT: [[EXITCOND_PEEL5:%.*]] = icmp ne i32 [[INC_PEEL4]], 100000
61 ; CHECK-NEXT: br i1 [[EXITCOND_PEEL5]], label [[FOR_BODY_PEEL_NEXT1:%.*]], label [[FOR_COND_CLEANUP]]
62 ; CHECK: for.body.peel.next1:
63 ; CHECK-NEXT: br label [[FOR_BODY_PEEL7:%.*]]
64 ; CHECK: for.body.peel7:
65 ; CHECK-NEXT: tail call void @_Z1gi(i32 noundef signext [[CONV_PEEL3]])
66 ; CHECK-NEXT: [[CONV_PEEL8:%.*]] = fptosi float 5.000000e+00 to i32
67 ; CHECK-NEXT: tail call void @_Z1ff(float noundef 5.000000e+00)
68 ; CHECK-NEXT: [[INC_PEEL9:%.*]] = add nuw nsw i32 [[INC_PEEL4]], 1
69 ; CHECK-NEXT: [[EXITCOND_PEEL10:%.*]] = icmp ne i32 [[INC_PEEL9]], 100000
70 ; CHECK-NEXT: br i1 [[EXITCOND_PEEL10]], label [[FOR_BODY_PEEL_NEXT6:%.*]], label [[FOR_COND_CLEANUP]]
71 ; CHECK: for.body.peel.next6:
72 ; CHECK-NEXT: br label [[FOR_BODY_PEEL_NEXT11:%.*]]
73 ; CHECK: for.body.peel.next11:
74 ; CHECK-NEXT: br label [[ENTRY_PEEL_NEWPH:%.*]]
75 ; CHECK: entry.peel.newph:
76 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
77 ; CHECK: for.cond.cleanup.loopexit:
78 ; CHECK-NEXT: br label [[FOR_COND_CLEANUP]]
79 ; CHECK: for.cond.cleanup:
80 ; CHECK-NEXT: ret void
82 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[INC_PEEL9]], [[ENTRY_PEEL_NEWPH]] ], [ [[INC:%.*]], [[FOR_BODY]] ]
83 ; CHECK-NEXT: [[X:%.*]] = phi i32 [ [[CONV_PEEL8]], [[ENTRY_PEEL_NEWPH]] ], [ 5, [[FOR_BODY]] ]
84 ; CHECK-NEXT: tail call void @_Z1gi(i32 noundef signext [[X]])
85 ; CHECK-NEXT: tail call void @_Z1ff(float noundef 5.000000e+00)
86 ; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I]], 1
87 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[INC]], 100000
88 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], !llvm.loop [[LOOP0:![0-9]+]]
97 %i = phi i32 [ 0, %entry ], [ %inc, %for.body ]
98 %a = phi float [ 0.000000e+00, %entry ], [ 5.000000e+00, %for.body ]
99 %y = phi float [ 0.000000e+00, %entry ], [ %a, %for.body ]
100 %x = phi i32 [ 0, %entry ], [ %conv, %for.body ]
101 tail call void @_Z1gi(i32 noundef signext %x)
102 %conv = fptosi float %y to i32
103 tail call void @_Z1ff(float noundef %y)
104 %inc = add nuw nsw i32 %i, 1
105 %exitcond = icmp ne i32 %inc, 100000
106 br i1 %exitcond, label %for.body, label %for.cond.cleanup
109 ; Check that phi analysis can handle a binary operator.
110 define void @_Z6binaryv() {
111 ; The phis become invariant through the chain of phis, with a unary
112 ; instruction on a loop invariant. Check that the phis for x, a, and y
113 ; are removed since x is based on y, which is based on a, which is based
114 ; on a binary add of a phi and a constant.
115 ; Consider the calls to g:
116 ; First iteration: g(0), x=0, g(0), y=1, a=5
117 ; Second iteration: g(0), x=1, g(5), y=6(binary operator), a=5
118 ; Third iteration: g(1), x=6, g(5), y=6, a=5
119 ; Fourth iteration (and subsequent): g(6), x=6, g(5), y=6, a=5
120 ; Therefore, peeling 3 times removes the phi nodes.
127 ; for(int i = 0; i <100000; ++i) {
136 ; CHECK-LABEL: @_Z6binaryv(
138 ; CHECK-NEXT: br label [[FOR_BODY_PEEL_BEGIN:%.*]]
139 ; CHECK: for.body.peel.begin:
140 ; CHECK-NEXT: br label [[FOR_BODY_PEEL:%.*]]
141 ; CHECK: for.body.peel:
142 ; CHECK-NEXT: tail call void @_Z1gi(i32 signext 0)
143 ; CHECK-NEXT: tail call void @_Z1gi(i32 signext 0)
144 ; CHECK-NEXT: [[ADD_PEEL:%.*]] = add nuw nsw i32 0, 1
145 ; CHECK-NEXT: [[INC_PEEL:%.*]] = add nuw nsw i32 0, 1
146 ; CHECK-NEXT: [[EXITCOND_PEEL:%.*]] = icmp eq i32 [[INC_PEEL]], 100000
147 ; CHECK-NEXT: br i1 [[EXITCOND_PEEL]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY_PEEL_NEXT:%.*]]
148 ; CHECK: for.body.peel.next:
149 ; CHECK-NEXT: br label [[FOR_BODY_PEEL2:%.*]]
150 ; CHECK: for.body.peel2:
151 ; CHECK-NEXT: tail call void @_Z1gi(i32 signext 0)
152 ; CHECK-NEXT: tail call void @_Z1gi(i32 signext 5)
153 ; CHECK-NEXT: [[INC_PEEL4:%.*]] = add nuw nsw i32 [[INC_PEEL]], 1
154 ; CHECK-NEXT: [[EXITCOND_PEEL5:%.*]] = icmp eq i32 [[INC_PEEL4]], 100000
155 ; CHECK-NEXT: br i1 [[EXITCOND_PEEL5]], label [[FOR_COND_CLEANUP]], label [[FOR_BODY_PEEL_NEXT1:%.*]]
156 ; CHECK: for.body.peel.next1:
157 ; CHECK-NEXT: br label [[FOR_BODY_PEEL7:%.*]]
158 ; CHECK: for.body.peel7:
159 ; CHECK-NEXT: tail call void @_Z1gi(i32 signext [[ADD_PEEL]])
160 ; CHECK-NEXT: tail call void @_Z1gi(i32 signext 5)
161 ; CHECK-NEXT: [[INC_PEEL9:%.*]] = add nuw nsw i32 [[INC_PEEL4]], 1
162 ; CHECK-NEXT: [[EXITCOND_PEEL10:%.*]] = icmp eq i32 [[INC_PEEL9]], 100000
163 ; CHECK-NEXT: br i1 [[EXITCOND_PEEL10]], label [[FOR_COND_CLEANUP]], label [[FOR_BODY_PEEL_NEXT6:%.*]]
164 ; CHECK: for.body.peel.next6:
165 ; CHECK-NEXT: br label [[FOR_BODY_PEEL_NEXT11:%.*]]
166 ; CHECK: for.body.peel.next11:
167 ; CHECK-NEXT: br label [[ENTRY_PEEL_NEWPH:%.*]]
168 ; CHECK: entry.peel.newph:
169 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
170 ; CHECK: for.cond.cleanup.loopexit:
171 ; CHECK-NEXT: br label [[FOR_COND_CLEANUP]]
172 ; CHECK: for.cond.cleanup:
173 ; CHECK-NEXT: ret void
175 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[INC_PEEL9]], [[ENTRY_PEEL_NEWPH]] ], [ [[INC:%.*]], [[FOR_BODY]] ]
176 ; CHECK-NEXT: tail call void @_Z1gi(i32 signext 6)
177 ; CHECK-NEXT: tail call void @_Z1gi(i32 signext 5)
178 ; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I]], 1
179 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 100000
180 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[FOR_BODY]], !llvm.loop [[LOOP2:![0-9]+]]
189 %i = phi i32 [ 0, %entry ], [ %inc, %for.body ]
190 %a = phi i32 [ 0, %entry ], [ 5, %for.body ]
191 %y = phi i32 [ 0, %entry ], [ %add, %for.body ]
192 %x = phi i32 [ 0, %entry ], [ %y, %for.body ]
193 tail call void @_Z1gi(i32 signext %x)
194 tail call void @_Z1gi(i32 signext %a)
195 %add = add nuw nsw i32 %a, 1
196 %inc = add nuw nsw i32 %i, 1
197 %exitcond = icmp eq i32 %inc, 100000
198 br i1 %exitcond, label %for.cond.cleanup, label %for.body