xref: /llvm-project/llvm/test/Transforms/NewGVN/phi-of-ops-loads.ll (revision a1f5ea5b5f1fd9fd7607731af839587c325c42a9)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes=newgvn -enable-phi-of-ops=true -S -o - %s | FileCheck %s
3
4define void @hoisted-load(ptr %p, ptr %q) {
5; CHECK-LABEL: @hoisted-load(
6; CHECK-NEXT:  bb56:
7; CHECK-NEXT:    [[N60:%.*]] = load i8, ptr [[P:%.*]], align 1
8; CHECK-NEXT:    br label [[BB57:%.*]]
9; CHECK:       bb57:
10; CHECK-NEXT:    [[PHIOFOPS:%.*]] = phi i1 [ true, [[BB56:%.*]] ], [ [[N62:%.*]], [[BB229:%.*]] ]
11; CHECK-NEXT:    [[N59:%.*]] = phi i1 [ false, [[BB229]] ], [ true, [[BB56]] ]
12; CHECK-NEXT:    [[IDX:%.*]] = phi i8 [ 0, [[BB56]] ], [ [[INC:%.*]], [[BB229]] ]
13; CHECK-NEXT:    [[N62]] = icmp ne i8 [[N60]], 2
14; CHECK-NEXT:    br i1 [[PHIOFOPS]], label [[BB229]], label [[BB237:%.*]]
15; CHECK:       bb229:
16; CHECK-NEXT:    [[INC]] = add i8 [[IDX]], 1
17; CHECK-NEXT:    store i8 [[INC]], ptr [[Q:%.*]], align 1
18; CHECK-NEXT:    br label [[BB57]]
19; CHECK:       bb237:
20; CHECK-NEXT:    ret void
21;
22bb56:
23  %n60 = load i8, ptr %p
24  br label %bb57
25
26bb57:
27  %n59 = phi i1 [ false, %bb229 ], [ true, %bb56 ]
28  %idx = phi i8 [0, %bb56], [%inc, %bb229]
29  %n62 = icmp ne i8 %n60, 2
30  %n63 = or i1 %n59, %n62
31  br i1 %n63, label %bb229, label %bb237
32
33bb229:
34  %inc = add i8 %idx, 1
35  store i8 %inc, ptr %q
36  br label %bb57
37
38bb237:
39  ret void
40}
41
42define void @store-in-loop(ptr %p, ptr %q) {
43; CHECK-LABEL: @store-in-loop(
44; CHECK-NEXT:  bb56:
45; CHECK-NEXT:    br label [[BB57:%.*]]
46; CHECK:       bb57:
47; CHECK-NEXT:    [[N59:%.*]] = phi i1 [ false, [[BB229:%.*]] ], [ true, [[BB56:%.*]] ]
48; CHECK-NEXT:    [[IDX:%.*]] = phi i8 [ 0, [[BB56]] ], [ [[INC:%.*]], [[BB229]] ]
49; CHECK-NEXT:    [[N60:%.*]] = load i8, ptr [[P:%.*]], align 1
50; CHECK-NEXT:    [[N62:%.*]] = icmp ne i8 [[N60]], 2
51; CHECK-NEXT:    [[N63:%.*]] = or i1 [[N59]], [[N62]]
52; CHECK-NEXT:    br i1 [[N63]], label [[BB229]], label [[BB237:%.*]]
53; CHECK:       bb229:
54; CHECK-NEXT:    [[INC]] = add i8 [[IDX]], 1
55; CHECK-NEXT:    store i8 [[INC]], ptr [[Q:%.*]], align 1
56; CHECK-NEXT:    br label [[BB57]]
57; CHECK:       bb237:
58; CHECK-NEXT:    ret void
59;
60bb56:
61  br label %bb57
62
63bb57:
64  %n59 = phi i1 [ false, %bb229 ], [ true, %bb56 ]
65  %idx = phi i8 [0, %bb56], [%inc, %bb229]
66  %n60 = load i8, ptr %p
67  %n62 = icmp ne i8 %n60, 2
68  %n63 = or i1 %n59, %n62
69  br i1 %n63, label %bb229, label %bb237
70
71bb229:
72  %inc = add i8 %idx, 1
73  store i8 %inc, ptr %q
74  br label %bb57
75
76bb237:
77  ret void
78}
79
80; TODO: we should support this case
81define void @no-alias-store-in-loop(ptr noalias %p, ptr noalias %q) {
82; CHECK-LABEL: @no-alias-store-in-loop(
83; CHECK-NEXT:  bb56:
84; CHECK-NEXT:    br label [[BB57:%.*]]
85; CHECK:       bb57:
86; CHECK-NEXT:    [[N59:%.*]] = phi i1 [ false, [[BB229:%.*]] ], [ true, [[BB56:%.*]] ]
87; CHECK-NEXT:    [[IDX:%.*]] = phi i8 [ 0, [[BB56]] ], [ [[INC:%.*]], [[BB229]] ]
88; CHECK-NEXT:    [[N60:%.*]] = load i8, ptr [[P:%.*]], align 1
89; CHECK-NEXT:    [[N62:%.*]] = icmp ne i8 [[N60]], 2
90; CHECK-NEXT:    [[N63:%.*]] = or i1 [[N59]], [[N62]]
91; CHECK-NEXT:    br i1 [[N63]], label [[BB229]], label [[BB237:%.*]]
92; CHECK:       bb229:
93; CHECK-NEXT:    [[INC]] = add i8 [[IDX]], 1
94; CHECK-NEXT:    store i8 [[INC]], ptr [[Q:%.*]], align 1
95; CHECK-NEXT:    br label [[BB57]]
96; CHECK:       bb237:
97; CHECK-NEXT:    ret void
98;
99bb56:
100  br label %bb57
101
102bb57:
103  %n59 = phi i1 [ false, %bb229 ], [ true, %bb56 ]
104  %idx = phi i8 [0, %bb56], [%inc, %bb229]
105  %n60 = load i8, ptr %p
106  %n62 = icmp ne i8 %n60, 2
107  %n63 = or i1 %n59, %n62
108  br i1 %n63, label %bb229, label %bb237
109
110bb229:
111  %inc = add i8 %idx, 1
112  store i8 %inc, ptr %q
113  br label %bb57
114
115bb237:
116  ret void
117}
118
119define void @function-in-loop(ptr %p) {
120; CHECK-LABEL: @function-in-loop(
121; CHECK-NEXT:  bb56:
122; CHECK-NEXT:    br label [[BB57:%.*]]
123; CHECK:       bb57:
124; CHECK-NEXT:    [[N59:%.*]] = phi i1 [ false, [[BB229:%.*]] ], [ true, [[BB56:%.*]] ]
125; CHECK-NEXT:    [[N60:%.*]] = load i8, ptr [[P:%.*]], align 1
126; CHECK-NEXT:    [[N62:%.*]] = icmp ne i8 [[N60]], 2
127; CHECK-NEXT:    [[N63:%.*]] = or i1 [[N59]], [[N62]]
128; CHECK-NEXT:    br i1 [[N63]], label [[BB229]], label [[BB237:%.*]]
129; CHECK:       bb229:
130; CHECK-NEXT:    call void @f()
131; CHECK-NEXT:    br label [[BB57]]
132; CHECK:       bb237:
133; CHECK-NEXT:    ret void
134;
135bb56:
136  br label %bb57
137
138bb57:
139  %n59 = phi i1 [ false, %bb229 ], [ true, %bb56 ]
140  %n60 = load i8, ptr %p
141  %n62 = icmp ne i8 %n60, 2
142  %n63 = or i1 %n59, %n62
143  br i1 %n63, label %bb229, label %bb237
144
145bb229:
146  call void @f()
147  br label %bb57
148
149bb237:
150  ret void
151}
152
153; TODO: we should support this case
154define void @nowrite-function-in-loop(ptr %p) {
155; CHECK-LABEL: @nowrite-function-in-loop(
156; CHECK-NEXT:  bb56:
157; CHECK-NEXT:    br label [[BB57:%.*]]
158; CHECK:       bb57:
159; CHECK-NEXT:    [[N59:%.*]] = phi i1 [ false, [[BB229:%.*]] ], [ true, [[BB56:%.*]] ]
160; CHECK-NEXT:    [[N60:%.*]] = load i8, ptr [[P:%.*]], align 1
161; CHECK-NEXT:    [[N62:%.*]] = icmp ne i8 [[N60]], 2
162; CHECK-NEXT:    [[N63:%.*]] = or i1 [[N59]], [[N62]]
163; CHECK-NEXT:    br i1 [[N63]], label [[BB229]], label [[BB237:%.*]]
164; CHECK:       bb229:
165; CHECK-NEXT:    call void @f() #[[ATTR0:[0-9]+]]
166; CHECK-NEXT:    br label [[BB57]]
167; CHECK:       bb237:
168; CHECK-NEXT:    ret void
169;
170bb56:
171  br label %bb57
172
173bb57:
174  %n59 = phi i1 [ false, %bb229 ], [ true, %bb56 ]
175  %n60 = load i8, ptr %p
176  %n62 = icmp ne i8 %n60, 2
177  %n63 = or i1 %n59, %n62
178  br i1 %n63, label %bb229, label %bb237
179
180bb229:
181  call void @f() inaccessiblememonly
182  br label %bb57
183
184bb237:
185  ret void
186}
187
188declare void @f()
189
190define void @issfeoperand(ptr nocapture readonly %array, i1 %cond1, i1 %cond2, ptr nocapture readonly %p1, ptr nocapture writeonly %p2, ptr nocapture writeonly %p3) local_unnamed_addr #0 {
191; CHECK-LABEL: @issfeoperand(
192; CHECK-NEXT:  for.body:
193; CHECK-NEXT:    br i1 [[COND1:%.*]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
194; CHECK:       cond.true:
195; CHECK-NEXT:    [[ARRAYIDX31:%.*]] = getelementptr inbounds [3 x [2 x [1 x i8]]], ptr [[ARRAY:%.*]], i64 109, i64 0, i64 0, i64 undef
196; CHECK-NEXT:    [[LD1:%.*]] = load i8, ptr [[ARRAYIDX31]], align 1
197; CHECK-NEXT:    br label [[COND_FALSE]]
198; CHECK:       cond.false:
199; CHECK-NEXT:    [[PHI1:%.*]] = phi i8 [ [[LD1]], [[COND_TRUE]] ], [ 0, [[FOR_BODY:%.*]] ]
200; CHECK-NEXT:    [[ARRAYIDX42:%.*]] = getelementptr inbounds [3 x [2 x [1 x i8]]], ptr [[ARRAY]], i64 109, i64 0, i64 0, i64 undef
201; CHECK-NEXT:    [[LD2:%.*]] = load i8, ptr [[ARRAYIDX42]], align 1
202; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i8 [[LD2]], [[PHI1]]
203; CHECK-NEXT:    [[ZEXT:%.*]] = zext i1 [[CMP1]] to i32
204; CHECK-NEXT:    store i32 [[ZEXT]], ptr [[P2:%.*]], align 4
205; CHECK-NEXT:    br i1 [[COND2:%.*]], label [[COND_END:%.*]], label [[EXIT:%.*]]
206; CHECK:       cond.end:
207; CHECK-NEXT:    [[LD3:%.*]] = load i16, ptr [[P1:%.*]], align 2
208; CHECK-NEXT:    [[SEXT:%.*]] = sext i16 [[LD3]] to i32
209; CHECK-NEXT:    br label [[EXIT]]
210; CHECK:       exit:
211; CHECK-NEXT:    [[PHI2:%.*]] = phi i32 [ [[SEXT]], [[COND_END]] ], [ 0, [[COND_FALSE]] ]
212; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i8 [[LD2]], 0
213; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP2]], i32 [[PHI2]], i32 0
214; CHECK-NEXT:    store i32 [[SEL]], ptr [[P3:%.*]], align 4
215; CHECK-NEXT:    ret void
216;
217for.body:
218  br i1 %cond1, label %cond.true, label %cond.false
219
220cond.true:                                        ; preds = %for.body
221  %arrayidx31 = getelementptr inbounds [3 x [2 x [1 x i8]]], ptr %array, i64 109, i64 0, i64 0, i64 undef
222  %ld1 = load i8, ptr %arrayidx31, align 1
223  br label %cond.false
224
225cond.false:                                       ; preds = %cond.true, %for.body
226  %phi1 = phi i8 [ %ld1, %cond.true ], [ 0, %for.body ]
227  %arrayidx42 = getelementptr inbounds [3 x [2 x [1 x i8]]], ptr %array, i64 109, i64 0, i64 0, i64 undef
228  %ld2 = load i8, ptr %arrayidx42, align 1
229  %cmp1 = icmp ult i8 %ld2, %phi1
230  %zext = zext i1 %cmp1 to i32
231  store i32 %zext, ptr %p2, align 4
232  br i1 %cond2, label %cond.end, label %exit
233
234cond.end:                                         ; preds = %cond.false
235  %ld3 = load i16, ptr %p1, align 2
236  %sext = sext i16 %ld3 to i32
237  br label %exit
238
239exit:                                             ; preds = %cond.end, %cond.false
240  %phi2 = phi i32 [ %sext, %cond.end ], [ 0, %cond.false ]
241  %cmp2 = icmp eq i8 %ld2, 0
242  %sel = select i1 %cmp2, i32 %phi2, i32 0
243  store i32 %sel, ptr %p3, align 4
244  ret void
245}
246