@@ -241,3 +241,249 @@ exit:
241241 store float %vl.1.lcssa , ptr @A
242242 ret void
243243}
244+
245+ ; The difference from select_with_identical_phi() is that not all phis are sorted with
246+ ; the same order of incoming BBs.
247+ ; Check that %same.as.v1 can be folded.
248+ define void @select_with_identical_phi_5 (ptr %m , ptr %n , i32 %count ) {
249+ ; CHECK-LABEL: @select_with_identical_phi_5(
250+ ; CHECK-NEXT: entry:
251+ ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
252+ ; CHECK: for.body:
253+ ; CHECK-NEXT: [[V0:%.*]] = phi float [ 0x4415AF1D80000000, [[ENTRY:%.*]] ], [ [[V0_1:%.*]], [[FOR_BODY]] ]
254+ ; CHECK-NEXT: [[V1:%.*]] = phi float [ 0xC415AF1D80000000, [[ENTRY]] ], [ [[V1_1:%.*]], [[FOR_BODY]] ]
255+ ; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC_I:%.*]], [[FOR_BODY]] ]
256+ ; CHECK-NEXT: [[Q:%.*]] = phi ptr [ [[M:%.*]], [[ENTRY]] ], [ [[Q_NEXT:%.*]], [[FOR_BODY]] ]
257+ ; CHECK-NEXT: [[C:%.*]] = phi ptr [ [[N:%.*]], [[ENTRY]] ], [ [[C_NEXT:%.*]], [[FOR_BODY]] ]
258+ ; CHECK-NEXT: [[Q_LOAD:%.*]] = load float, ptr [[Q]], align 4
259+ ; CHECK-NEXT: [[C_LOAD:%.*]] = load float, ptr [[C]], align 4
260+ ; CHECK-NEXT: [[SUB:%.*]] = fsub float [[Q_LOAD]], [[C_LOAD]]
261+ ; CHECK-NEXT: [[CMP1:%.*]] = fcmp olt float [[SUB]], [[V0]]
262+ ; CHECK-NEXT: [[V0_1]] = select i1 [[CMP1]], float [[SUB]], float [[V0]]
263+ ; CHECK-NEXT: [[CMP2:%.*]] = fcmp ogt float [[SUB]], [[V1]]
264+ ; CHECK-NEXT: [[V1_1]] = select i1 [[CMP2]], float [[SUB]], float [[V1]]
265+ ; CHECK-NEXT: [[INC_I]] = add nuw nsw i32 [[I]], 1
266+ ; CHECK-NEXT: [[Q_NEXT]] = getelementptr inbounds nuw i8, ptr [[Q]], i64 4
267+ ; CHECK-NEXT: [[C_NEXT]] = getelementptr inbounds nuw i8, ptr [[C]], i64 4
268+ ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC_I]], [[COUNT:%.*]]
269+ ; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[FOR_BODY]]
270+ ; CHECK: exit:
271+ ; CHECK-NEXT: store float [[V1_1]], ptr @A, align 4
272+ ; CHECK-NEXT: ret void
273+ ;
274+ entry:
275+ br label %for.body
276+
277+ for.body: ; preds = %entry, %for.body
278+ %v0 = phi float [ 0x4415AF1D80000000 , %entry ], [ %v0.1 , %for.body ]
279+ %v1 = phi float [ 0xC415AF1D80000000 , %entry ], [ %v1.1 , %for.body ]
280+ %phi.to.remove = phi float [ %phi.to.remove.next , %for.body ], [ 0xC415AF1D80000000 , %entry ]
281+ %i = phi i32 [ 0 , %entry ], [ %inc.i , %for.body ]
282+ %q = phi ptr [ %m , %entry ], [ %q.next , %for.body ]
283+ %c = phi ptr [ %n , %entry ], [ %c.next , %for.body ]
284+ %q.load = load float , ptr %q
285+ %c.load = load float , ptr %c
286+ %sub = fsub float %q.load , %c.load
287+ %cmp1 = fcmp olt float %sub , %v0
288+ %v0.1 = select i1 %cmp1 , float %sub , float %v0
289+ %same.as.v1 = select i1 %cmp1 , float %v1 , float %phi.to.remove
290+ %cmp2 = fcmp ogt float %sub , %same.as.v1
291+ %v1.1 = select i1 %cmp2 , float %sub , float %v1
292+ %phi.to.remove.next = select i1 %cmp2 , float %sub , float %same.as.v1
293+ %inc.i = add nuw nsw i32 %i , 1
294+ %q.next = getelementptr inbounds i8 , ptr %q , i64 4
295+ %c.next = getelementptr inbounds i8 , ptr %c , i64 4
296+ %exitcond = icmp eq i32 %inc.i , %count
297+ br i1 %exitcond , label %exit , label %for.body
298+
299+ exit:
300+ %vl.1.lcssa = phi float [ %v1.1 , %for.body ]
301+ store float %vl.1.lcssa , ptr @A
302+ ret void
303+ }
304+
305+ ; %v1 and %phi.to.remove do not have the same start value.
306+ ; Cannot fold %same.as.v1.
307+ define void @select_with_identical_phi_negative_1 (ptr %m , ptr %n , i32 %count ) {
308+ ; CHECK-LABEL: @select_with_identical_phi_negative_1(
309+ ; CHECK-NEXT: entry:
310+ ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
311+ ; CHECK: for.body:
312+ ; CHECK-NEXT: [[V0:%.*]] = phi float [ 0x4415AF1D80000000, [[ENTRY:%.*]] ], [ [[V0_1:%.*]], [[FOR_BODY]] ]
313+ ; CHECK-NEXT: [[V1:%.*]] = phi float [ 0x4415AF1D80000000, [[ENTRY]] ], [ [[V1_1:%.*]], [[FOR_BODY]] ]
314+ ; CHECK-NEXT: [[PHI_TO_REMOVE:%.*]] = phi float [ 0xC415AF1D80000000, [[ENTRY]] ], [ [[PHI_TO_REMOVE_NEXT:%.*]], [[FOR_BODY]] ]
315+ ; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC_I:%.*]], [[FOR_BODY]] ]
316+ ; CHECK-NEXT: [[Q:%.*]] = phi ptr [ [[M:%.*]], [[ENTRY]] ], [ [[Q_NEXT:%.*]], [[FOR_BODY]] ]
317+ ; CHECK-NEXT: [[C:%.*]] = phi ptr [ [[N:%.*]], [[ENTRY]] ], [ [[C_NEXT:%.*]], [[FOR_BODY]] ]
318+ ; CHECK-NEXT: [[Q_LOAD:%.*]] = load float, ptr [[Q]], align 4
319+ ; CHECK-NEXT: [[C_LOAD:%.*]] = load float, ptr [[C]], align 4
320+ ; CHECK-NEXT: [[SUB:%.*]] = fsub float [[Q_LOAD]], [[C_LOAD]]
321+ ; CHECK-NEXT: [[CMP1:%.*]] = fcmp olt float [[SUB]], [[V0]]
322+ ; CHECK-NEXT: [[V0_1]] = select i1 [[CMP1]], float [[SUB]], float [[V0]]
323+ ; CHECK-NEXT: [[SAME_AS_V1:%.*]] = select i1 [[CMP1]], float [[V1]], float [[PHI_TO_REMOVE]]
324+ ; CHECK-NEXT: [[CMP2:%.*]] = fcmp ogt float [[SUB]], [[SAME_AS_V1]]
325+ ; CHECK-NEXT: [[V1_1]] = select i1 [[CMP2]], float [[SUB]], float [[V1]]
326+ ; CHECK-NEXT: [[PHI_TO_REMOVE_NEXT]] = select i1 [[CMP2]], float [[SUB]], float [[SAME_AS_V1]]
327+ ; CHECK-NEXT: [[INC_I]] = add nuw nsw i32 [[I]], 1
328+ ; CHECK-NEXT: [[Q_NEXT]] = getelementptr inbounds nuw i8, ptr [[Q]], i64 4
329+ ; CHECK-NEXT: [[C_NEXT]] = getelementptr inbounds nuw i8, ptr [[C]], i64 4
330+ ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC_I]], [[COUNT:%.*]]
331+ ; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[FOR_BODY]]
332+ ; CHECK: exit:
333+ ; CHECK-NEXT: store float [[V1_1]], ptr @A, align 4
334+ ; CHECK-NEXT: ret void
335+ ;
336+ entry:
337+ br label %for.body
338+
339+ for.body: ; preds = %entry, %for.body
340+ %v0 = phi float [ 0x4415AF1D80000000 , %entry ], [ %v0.1 , %for.body ]
341+ %v1 = phi float [ 0x4415AF1D80000000 , %entry ], [ %v1.1 , %for.body ]
342+ %phi.to.remove = phi float [ 0xC415AF1D80000000 , %entry ], [ %phi.to.remove.next , %for.body ]
343+ %i = phi i32 [ 0 , %entry ], [ %inc.i , %for.body ]
344+ %q = phi ptr [ %m , %entry ], [ %q.next , %for.body ]
345+ %c = phi ptr [ %n , %entry ], [ %c.next , %for.body ]
346+ %q.load = load float , ptr %q
347+ %c.load = load float , ptr %c
348+ %sub = fsub float %q.load , %c.load
349+ %cmp1 = fcmp olt float %sub , %v0
350+ %v0.1 = select i1 %cmp1 , float %sub , float %v0
351+ %same.as.v1 = select i1 %cmp1 , float %v1 , float %phi.to.remove
352+ %cmp2 = fcmp ogt float %sub , %same.as.v1
353+ %v1.1 = select i1 %cmp2 , float %sub , float %v1
354+ %phi.to.remove.next = select i1 %cmp2 , float %sub , float %same.as.v1
355+ %inc.i = add nuw nsw i32 %i , 1
356+ %q.next = getelementptr inbounds i8 , ptr %q , i64 4
357+ %c.next = getelementptr inbounds i8 , ptr %c , i64 4
358+ %exitcond = icmp eq i32 %inc.i , %count
359+ br i1 %exitcond , label %exit , label %for.body
360+
361+ exit:
362+ %vl.1.lcssa = phi float [ %v1.1 , %for.body ]
363+ store float %vl.1.lcssa , ptr @A
364+ ret void
365+ }
366+
367+ ; %v1 and %phi.to.remove do not act as the same phi since %v1.1 and %phi.to.remove.next do not evolve the same.
368+ ; Cannot fold %same.as.v1.
369+ define void @select_with_identical_phi_negative_2 (ptr %m , ptr %n , i32 %count ) {
370+ ; CHECK-LABEL: @select_with_identical_phi_negative_2(
371+ ; CHECK-NEXT: entry:
372+ ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
373+ ; CHECK: for.body:
374+ ; CHECK-NEXT: [[V0:%.*]] = phi float [ 0x4415AF1D80000000, [[ENTRY:%.*]] ], [ [[V0_1:%.*]], [[FOR_BODY]] ]
375+ ; CHECK-NEXT: [[V1:%.*]] = phi float [ 0xC415AF1D80000000, [[ENTRY]] ], [ [[V1_1:%.*]], [[FOR_BODY]] ]
376+ ; CHECK-NEXT: [[PHI_TO_REMOVE:%.*]] = phi float [ 0xC415AF1D80000000, [[ENTRY]] ], [ [[PHI_TO_REMOVE_NEXT:%.*]], [[FOR_BODY]] ]
377+ ; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC_I:%.*]], [[FOR_BODY]] ]
378+ ; CHECK-NEXT: [[Q:%.*]] = phi ptr [ [[M:%.*]], [[ENTRY]] ], [ [[Q_NEXT:%.*]], [[FOR_BODY]] ]
379+ ; CHECK-NEXT: [[C:%.*]] = phi ptr [ [[N:%.*]], [[ENTRY]] ], [ [[C_NEXT:%.*]], [[FOR_BODY]] ]
380+ ; CHECK-NEXT: [[Q_LOAD:%.*]] = load float, ptr [[Q]], align 4
381+ ; CHECK-NEXT: [[C_LOAD:%.*]] = load float, ptr [[C]], align 4
382+ ; CHECK-NEXT: [[SUB:%.*]] = fsub float [[Q_LOAD]], [[C_LOAD]]
383+ ; CHECK-NEXT: [[CMP1:%.*]] = fcmp olt float [[SUB]], [[V0]]
384+ ; CHECK-NEXT: [[V0_1]] = select i1 [[CMP1]], float [[SUB]], float [[V0]]
385+ ; CHECK-NEXT: [[SAME_AS_V1:%.*]] = select i1 [[CMP1]], float [[V1]], float [[PHI_TO_REMOVE]]
386+ ; CHECK-NEXT: [[CMP2:%.*]] = fcmp ogt float [[SUB]], [[SAME_AS_V1]]
387+ ; CHECK-NEXT: [[V1_1]] = select i1 [[CMP2]], float [[V1]], float [[SUB]]
388+ ; CHECK-NEXT: [[PHI_TO_REMOVE_NEXT]] = select i1 [[CMP2]], float [[SUB]], float [[SAME_AS_V1]]
389+ ; CHECK-NEXT: [[INC_I]] = add nuw nsw i32 [[I]], 1
390+ ; CHECK-NEXT: [[Q_NEXT]] = getelementptr inbounds nuw i8, ptr [[Q]], i64 4
391+ ; CHECK-NEXT: [[C_NEXT]] = getelementptr inbounds nuw i8, ptr [[C]], i64 4
392+ ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC_I]], [[COUNT:%.*]]
393+ ; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[FOR_BODY]]
394+ ; CHECK: exit:
395+ ; CHECK-NEXT: store float [[V1_1]], ptr @A, align 4
396+ ; CHECK-NEXT: ret void
397+ ;
398+ entry:
399+ br label %for.body
400+
401+ for.body: ; preds = %entry, %for.body
402+ %v0 = phi float [ 0x4415AF1D80000000 , %entry ], [ %v0.1 , %for.body ]
403+ %v1 = phi float [ 0xC415AF1D80000000 , %entry ], [ %v1.1 , %for.body ]
404+ %phi.to.remove = phi float [ 0xC415AF1D80000000 , %entry ], [ %phi.to.remove.next , %for.body ]
405+ %i = phi i32 [ 0 , %entry ], [ %inc.i , %for.body ]
406+ %q = phi ptr [ %m , %entry ], [ %q.next , %for.body ]
407+ %c = phi ptr [ %n , %entry ], [ %c.next , %for.body ]
408+ %q.load = load float , ptr %q
409+ %c.load = load float , ptr %c
410+ %sub = fsub float %q.load , %c.load
411+ %cmp1 = fcmp olt float %sub , %v0
412+ %v0.1 = select i1 %cmp1 , float %sub , float %v0
413+ %same.as.v1 = select i1 %cmp1 , float %v1 , float %phi.to.remove
414+ %cmp2 = fcmp ogt float %sub , %same.as.v1
415+ %v1.1 = select i1 %cmp2 , float %v1 , float %sub
416+ %phi.to.remove.next = select i1 %cmp2 , float %sub , float %same.as.v1
417+ %inc.i = add nuw nsw i32 %i , 1
418+ %q.next = getelementptr inbounds i8 , ptr %q , i64 4
419+ %c.next = getelementptr inbounds i8 , ptr %c , i64 4
420+ %exitcond = icmp eq i32 %inc.i , %count
421+ br i1 %exitcond , label %exit , label %for.body
422+
423+ exit:
424+ %vl.1.lcssa = phi float [ %v1.1 , %for.body ]
425+ store float %vl.1.lcssa , ptr @A
426+ ret void
427+ }
428+
429+ ; The true and false values of %same.as.v1 are not really the same phi.
430+ ; Cannot fold %same.as.v1.
431+ define void @select_with_identical_phi_negative_3 (ptr %m , ptr %n , i32 %count ) {
432+ ; CHECK-LABEL: @select_with_identical_phi_negative_3(
433+ ; CHECK-NEXT: entry:
434+ ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
435+ ; CHECK: for.body:
436+ ; CHECK-NEXT: [[V0:%.*]] = phi float [ 0x4415AF1D80000000, [[ENTRY:%.*]] ], [ [[V0_1:%.*]], [[FOR_BODY]] ]
437+ ; CHECK-NEXT: [[V1:%.*]] = phi float [ 0xC415AF1D80000000, [[ENTRY]] ], [ [[V1_1:%.*]], [[FOR_BODY]] ]
438+ ; CHECK-NEXT: [[PHI_TO_REMOVE:%.*]] = phi float [ 0xC415AF1D80000000, [[ENTRY]] ], [ [[PHI_TO_REMOVE_NEXT:%.*]], [[FOR_BODY]] ]
439+ ; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC_I:%.*]], [[FOR_BODY]] ]
440+ ; CHECK-NEXT: [[Q:%.*]] = phi ptr [ [[M:%.*]], [[ENTRY]] ], [ [[Q_NEXT:%.*]], [[FOR_BODY]] ]
441+ ; CHECK-NEXT: [[C:%.*]] = phi ptr [ [[N:%.*]], [[ENTRY]] ], [ [[C_NEXT:%.*]], [[FOR_BODY]] ]
442+ ; CHECK-NEXT: [[Q_LOAD:%.*]] = load float, ptr [[Q]], align 4
443+ ; CHECK-NEXT: [[C_LOAD:%.*]] = load float, ptr [[C]], align 4
444+ ; CHECK-NEXT: [[SUB:%.*]] = fsub float [[Q_LOAD]], [[C_LOAD]]
445+ ; CHECK-NEXT: [[CMP1:%.*]] = fcmp olt float [[SUB]], [[V0]]
446+ ; CHECK-NEXT: [[V0_1]] = select i1 [[CMP1]], float [[SUB]], float [[V0]]
447+ ; CHECK-NEXT: [[SAME_AS_V1:%.*]] = select i1 [[CMP1]], float [[V0]], float [[PHI_TO_REMOVE]]
448+ ; CHECK-NEXT: [[CMP2:%.*]] = fcmp ogt float [[SUB]], [[SAME_AS_V1]]
449+ ; CHECK-NEXT: [[V1_1]] = select i1 [[CMP2]], float [[SUB]], float [[V1]]
450+ ; CHECK-NEXT: [[PHI_TO_REMOVE_NEXT]] = select i1 [[CMP2]], float [[SUB]], float [[SAME_AS_V1]]
451+ ; CHECK-NEXT: [[INC_I]] = add nuw nsw i32 [[I]], 1
452+ ; CHECK-NEXT: [[Q_NEXT]] = getelementptr inbounds nuw i8, ptr [[Q]], i64 4
453+ ; CHECK-NEXT: [[C_NEXT]] = getelementptr inbounds nuw i8, ptr [[C]], i64 4
454+ ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC_I]], [[COUNT:%.*]]
455+ ; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[FOR_BODY]]
456+ ; CHECK: exit:
457+ ; CHECK-NEXT: store float [[V1_1]], ptr @A, align 4
458+ ; CHECK-NEXT: ret void
459+ ;
460+ entry:
461+ br label %for.body
462+
463+ for.body: ; preds = %entry, %for.body
464+ %v0 = phi float [ 0x4415AF1D80000000 , %entry ], [ %v0.1 , %for.body ]
465+ %v1 = phi float [ 0xC415AF1D80000000 , %entry ], [ %v1.1 , %for.body ]
466+ %phi.to.remove = phi float [ 0xC415AF1D80000000 , %entry ], [ %phi.to.remove.next , %for.body ]
467+ %i = phi i32 [ 0 , %entry ], [ %inc.i , %for.body ]
468+ %q = phi ptr [ %m , %entry ], [ %q.next , %for.body ]
469+ %c = phi ptr [ %n , %entry ], [ %c.next , %for.body ]
470+ %q.load = load float , ptr %q
471+ %c.load = load float , ptr %c
472+ %sub = fsub float %q.load , %c.load
473+ %cmp1 = fcmp olt float %sub , %v0
474+ %v0.1 = select i1 %cmp1 , float %sub , float %v0
475+ %same.as.v1 = select i1 %cmp1 , float %v0 , float %phi.to.remove
476+ %cmp2 = fcmp ogt float %sub , %same.as.v1
477+ %v1.1 = select i1 %cmp2 , float %sub , float %v1
478+ %phi.to.remove.next = select i1 %cmp2 , float %sub , float %same.as.v1
479+ %inc.i = add nuw nsw i32 %i , 1
480+ %q.next = getelementptr inbounds i8 , ptr %q , i64 4
481+ %c.next = getelementptr inbounds i8 , ptr %c , i64 4
482+ %exitcond = icmp eq i32 %inc.i , %count
483+ br i1 %exitcond , label %exit , label %for.body
484+
485+ exit:
486+ %vl.1.lcssa = phi float [ %v1.1 , %for.body ]
487+ store float %vl.1.lcssa , ptr @A
488+ ret void
489+ }
0 commit comments