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