@@ -119,31 +119,29 @@ for.end:
119119; We can't use postindex addressing on the conditional load of qval and can't
120120; convert the loop condition to a compare with zero, so we should instead use
121121; offset addressing.
122- ; FIXME: Currently we don't notice the load of qval is conditional, and attempt
123- ; postindex addressing anyway.
124122define i32 @conditional_load (ptr %p , ptr %q , ptr %n ) {
125123; CHECK-LABEL: define i32 @conditional_load(
126124; CHECK-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], ptr [[N:%.*]]) {
127125; CHECK-NEXT: [[ENTRY:.*]]:
128126; CHECK-NEXT: br label %[[FOR_BODY:.*]]
129127; CHECK: [[FOR_BODY]]:
130128; CHECK-NEXT: [[LSR_IV1:%.*]] = phi ptr [ [[SCEVGEP2:%.*]], %[[FOR_INC:.*]] ], [ [[P]], %[[ENTRY]] ]
131- ; CHECK-NEXT: [[LSR_IV:%.*]] = phi ptr [ [[SCEVGEP:%.*]], %[[FOR_INC]] ], [ [[Q]], %[[ENTRY]] ]
132129; CHECK-NEXT: [[IDX:%.*]] = phi i64 [ [[IDX_NEXT:%.*]], %[[FOR_INC]] ], [ 0, %[[ENTRY]] ]
133130; CHECK-NEXT: [[RET:%.*]] = phi i32 [ [[RET_NEXT:%.*]], %[[FOR_INC]] ], [ 0, %[[ENTRY]] ]
134131; CHECK-NEXT: [[PVAL:%.*]] = load i32, ptr [[LSR_IV1]], align 4
135132; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[PVAL]], 0
136133; CHECK-NEXT: [[SCEVGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i64 4
137134; CHECK-NEXT: br i1 [[TOBOOL_NOT]], label %[[FOR_INC]], label %[[IF_THEN:.*]]
138135; CHECK: [[IF_THEN]]:
136+ ; CHECK-NEXT: [[TMP0:%.*]] = shl i64 [[IDX]], 2
137+ ; CHECK-NEXT: [[LSR_IV:%.*]] = getelementptr i8, ptr [[Q]], i64 [[TMP0]]
139138; CHECK-NEXT: [[QVAL:%.*]] = load i32, ptr [[LSR_IV]], align 4
140139; CHECK-NEXT: [[ADD:%.*]] = add i32 [[RET]], [[QVAL]]
141140; CHECK-NEXT: br label %[[FOR_INC]]
142141; CHECK: [[FOR_INC]]:
143142; CHECK-NEXT: [[RET_NEXT]] = phi i32 [ [[ADD]], %[[IF_THEN]] ], [ [[RET]], %[[FOR_BODY]] ]
144143; CHECK-NEXT: [[IDX_NEXT]] = add nuw nsw i64 [[IDX]], 1
145144; CHECK-NEXT: [[NVAL:%.*]] = load volatile i64, ptr [[N]], align 8
146- ; CHECK-NEXT: [[SCEVGEP]] = getelementptr i8, ptr [[LSR_IV]], i64 4
147145; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[IDX_NEXT]], [[NVAL]]
148146; CHECK-NEXT: br i1 [[CMP]], label %[[FOR_BODY]], label %[[EXIT:.*]]
149147; CHECK: [[EXIT]]:
@@ -176,3 +174,141 @@ for.inc:
176174exit:
177175 ret i32 %ret.next
178176}
177+
178+ ; We can use postindex addressing for both loads here, even though the second
179+ ; may not be executed on every loop iteration.
180+ define i32 @early_exit_load (ptr %p , ptr %q , ptr %n ) {
181+ ; CHECK-LABEL: define i32 @early_exit_load(
182+ ; CHECK-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], ptr [[N:%.*]]) {
183+ ; CHECK-NEXT: [[ENTRY:.*]]:
184+ ; CHECK-NEXT: br label %[[FOR_BODY:.*]]
185+ ; CHECK: [[FOR_BODY]]:
186+ ; CHECK-NEXT: [[LSR_IV1:%.*]] = phi ptr [ [[SCEVGEP2:%.*]], %[[FOR_INC:.*]] ], [ [[P]], %[[ENTRY]] ]
187+ ; CHECK-NEXT: [[LSR_IV:%.*]] = phi ptr [ [[SCEVGEP:%.*]], %[[FOR_INC]] ], [ [[Q]], %[[ENTRY]] ]
188+ ; CHECK-NEXT: [[RET_PHI:%.*]] = phi i32 [ [[ADD:%.*]], %[[FOR_INC]] ], [ 0, %[[ENTRY]] ]
189+ ; CHECK-NEXT: [[IDX:%.*]] = phi i64 [ [[IDX_NEXT:%.*]], %[[FOR_INC]] ], [ 0, %[[ENTRY]] ]
190+ ; CHECK-NEXT: [[PVAL:%.*]] = load i32, ptr [[LSR_IV1]], align 4
191+ ; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[PVAL]], 0
192+ ; CHECK-NEXT: [[SCEVGEP2]] = getelementptr i8, ptr [[LSR_IV1]], i64 4
193+ ; CHECK-NEXT: br i1 [[CMP1]], label %[[FOR_INC]], label %[[EXIT:.*]]
194+ ; CHECK: [[FOR_INC]]:
195+ ; CHECK-NEXT: [[QVAL:%.*]] = load i32, ptr [[LSR_IV]], align 4
196+ ; CHECK-NEXT: [[ADD]] = add nsw i32 [[QVAL]], [[RET_PHI]]
197+ ; CHECK-NEXT: [[IDX_NEXT]] = add nuw nsw i64 [[IDX]], 1
198+ ; CHECK-NEXT: [[NVAL:%.*]] = load volatile i64, ptr [[N]], align 8
199+ ; CHECK-NEXT: [[SCEVGEP]] = getelementptr i8, ptr [[LSR_IV]], i64 4
200+ ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i64 [[IDX_NEXT]], [[NVAL]]
201+ ; CHECK-NEXT: br i1 [[CMP2]], label %[[FOR_BODY]], label %[[EXIT]]
202+ ; CHECK: [[EXIT]]:
203+ ; CHECK-NEXT: [[RET:%.*]] = phi i32 [ [[RET_PHI]], %[[FOR_BODY]] ], [ [[ADD]], %[[FOR_INC]] ]
204+ ; CHECK-NEXT: ret i32 [[RET]]
205+ ;
206+ entry:
207+ br label %for.body
208+
209+ for.body:
210+ %ret.phi = phi i32 [ %add , %for.inc ], [ 0 , %entry ]
211+ %idx = phi i64 [ %idx.next , %for.inc ], [ 0 , %entry ]
212+ %paddr = getelementptr inbounds nuw i32 , ptr %p , i64 %idx
213+ %pval = load i32 , ptr %paddr , align 4
214+ %cmp1 = icmp eq i32 %pval , 0
215+ br i1 %cmp1 , label %for.inc , label %exit
216+
217+ for.inc:
218+ %qaddr = getelementptr inbounds nuw i32 , ptr %q , i64 %idx
219+ %qval = load i32 , ptr %qaddr , align 4
220+ %add = add nsw i32 %qval , %ret.phi
221+ %idx.next = add nuw nsw i64 %idx , 1
222+ %nval = load volatile i64 , ptr %n , align 8
223+ %cmp2 = icmp slt i64 %idx.next , %nval
224+ br i1 %cmp2 , label %for.body , label %exit
225+
226+ exit:
227+ %ret = phi i32 [ %ret.phi , %for.body ], [ %add , %for.inc ]
228+ ret i32 %ret
229+ }
230+
231+ ; The control-flow before and after the load of qval shouldn't prevent postindex
232+ ; addressing from happening.
233+ ; FIXME: We choose postindex addressing, but the scevgep is placed in for.inc so
234+ ; during codegen we will fail to actually generate a postindex load.
235+ define void @middle_block_load (ptr %p , ptr %q , i64 %n ) {
236+ ; CHECK-LABEL: define void @middle_block_load(
237+ ; CHECK-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i64 [[N:%.*]]) {
238+ ; CHECK-NEXT: [[ENTRY:.*]]:
239+ ; CHECK-NEXT: br label %[[FOR_BODY:.*]]
240+ ; CHECK: [[FOR_BODY]]:
241+ ; CHECK-NEXT: [[LSR_IV2:%.*]] = phi ptr [ [[SCEVGEP3:%.*]], %[[FOR_INC:.*]] ], [ [[P]], %[[ENTRY]] ]
242+ ; CHECK-NEXT: [[LSR_IV1:%.*]] = phi ptr [ [[SCEVGEP:%.*]], %[[FOR_INC]] ], [ [[Q]], %[[ENTRY]] ]
243+ ; CHECK-NEXT: [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], %[[FOR_INC]] ], [ [[N]], %[[ENTRY]] ]
244+ ; CHECK-NEXT: [[PVAL:%.*]] = load i32, ptr [[LSR_IV2]], align 4
245+ ; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[PVAL]], 0
246+ ; CHECK-NEXT: [[SCEVGEP3]] = getelementptr i8, ptr [[LSR_IV2]], i64 4
247+ ; CHECK-NEXT: br i1 [[CMP1]], label %[[IF_THEN1:.*]], label %[[IF_ELSE1:.*]]
248+ ; CHECK: [[IF_THEN1]]:
249+ ; CHECK-NEXT: tail call void @otherfn1()
250+ ; CHECK-NEXT: br label %[[IF_END:.*]]
251+ ; CHECK: [[IF_ELSE1]]:
252+ ; CHECK-NEXT: tail call void @otherfn2()
253+ ; CHECK-NEXT: br label %[[IF_END]]
254+ ; CHECK: [[IF_END]]:
255+ ; CHECK-NEXT: [[QVAL:%.*]] = load i32, ptr [[LSR_IV1]], align 4
256+ ; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[QVAL]], 0
257+ ; CHECK-NEXT: br i1 [[CMP2]], label %[[IF_THEN2:.*]], label %[[IF_ELSE2:.*]]
258+ ; CHECK: [[IF_THEN2]]:
259+ ; CHECK-NEXT: tail call void @otherfn1()
260+ ; CHECK-NEXT: br label %[[FOR_INC]]
261+ ; CHECK: [[IF_ELSE2]]:
262+ ; CHECK-NEXT: tail call void @otherfn2()
263+ ; CHECK-NEXT: br label %[[FOR_INC]]
264+ ; CHECK: [[FOR_INC]]:
265+ ; CHECK-NEXT: [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], -1
266+ ; CHECK-NEXT: [[SCEVGEP]] = getelementptr i8, ptr [[LSR_IV1]], i64 4
267+ ; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i64 [[LSR_IV_NEXT]], 0
268+ ; CHECK-NEXT: br i1 [[CMP3]], label %[[EXIT:.*]], label %[[FOR_BODY]]
269+ ; CHECK: [[EXIT]]:
270+ ; CHECK-NEXT: ret void
271+ ;
272+ entry:
273+ br label %for.body
274+
275+ for.body:
276+ %idx = phi i64 [ %idx.next , %for.inc ], [ 0 , %entry ]
277+ %paddr = getelementptr inbounds nuw i32 , ptr %p , i64 %idx
278+ %pval = load i32 , ptr %paddr , align 4
279+ %cmp1 = icmp sgt i32 %pval , 0
280+ br i1 %cmp1 , label %if.then1 , label %if.else1
281+
282+ if.then1:
283+ tail call void @otherfn1 ()
284+ br label %if.end
285+
286+ if.else1:
287+ tail call void @otherfn2 ()
288+ br label %if.end
289+
290+ if.end:
291+ %qaddr = getelementptr inbounds nuw i32 , ptr %q , i64 %idx
292+ %qval = load i32 , ptr %qaddr , align 4
293+ %cmp2 = icmp sgt i32 %qval , 0
294+ br i1 %cmp2 , label %if.then2 , label %if.else2
295+
296+ if.then2:
297+ tail call void @otherfn1 ()
298+ br label %for.inc
299+
300+ if.else2:
301+ tail call void @otherfn2 ()
302+ br label %for.inc
303+
304+ for.inc:
305+ %idx.next = add nuw nsw i64 %idx , 1
306+ %cmp3 = icmp eq i64 %idx.next , %n
307+ br i1 %cmp3 , label %exit , label %for.body
308+
309+ exit:
310+ ret void
311+ }
312+
313+ declare dso_local void @otherfn1 ()
314+ declare dso_local void @otherfn2 ()
0 commit comments