@@ -481,4 +481,290 @@ exit:
481
481
ret i1 %u
482
482
}
483
483
484
+ define i1 @multi_exiting_loop_eq_different_exits_const_compare_known (ptr %s ) {
485
+ ; CHECK-LABEL: define i1 @multi_exiting_loop_eq_different_exits_const_compare_known(
486
+ ; CHECK-SAME: ptr [[S:%.*]]) {
487
+ ; CHECK-NEXT: [[ENTRY:.*]]:
488
+ ; CHECK-NEXT: br label %[[LOOP_HEADER:.*]]
489
+ ; CHECK: [[LOOP_HEADER]]:
490
+ ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
491
+ ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[IV]], 1234
492
+ ; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[EXIT_1:.*]], label %[[LOOP_LATCH]]
493
+ ; CHECK: [[LOOP_LATCH]]:
494
+ ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]]
495
+ ; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1
496
+ ; CHECK-NEXT: [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10
497
+ ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
498
+ ; CHECK-NEXT: br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT_2:.*]]
499
+ ; CHECK: [[EXIT_1]]:
500
+ ; CHECK-NEXT: ret i1 true
501
+ ; CHECK: [[EXIT_2]]:
502
+ ; CHECK-NEXT: ret i1 true
503
+ ;
504
+ entry:
505
+ br label %loop.header
506
+
507
+ loop.header:
508
+ %iv = phi i32 [ 0 , %entry ], [ %iv.next , %loop.latch ]
509
+ %exitcond.not = icmp eq i32 %iv , 1234
510
+ br i1 %exitcond.not , label %exit.1 , label %loop.latch
511
+
512
+ loop.latch:
513
+ %arrayidx = getelementptr inbounds i8 , ptr %s , i32 %iv
514
+ %0 = load i8 , ptr %arrayidx , align 1
515
+ %latch.c = icmp ult i8 %0 , 10
516
+ %iv.next = add nuw nsw i32 %iv , 1
517
+ br i1 %latch.c , label %loop.header , label %exit.2
518
+
519
+ exit.1 :
520
+ %t.1 = icmp ult i32 %iv , 1235
521
+ ret i1 %t.1
522
+
523
+ exit.2 :
524
+ %t.2 = icmp ult i32 %iv , 1235
525
+ ret i1 %t.2
526
+ }
527
+
528
+ define i1 @multi_exiting_loop_eq_different_exits_2_const_compare_known (ptr %s , i1 %c.1 , i1 %c.2 ) {
529
+ ; CHECK-LABEL: define i1 @multi_exiting_loop_eq_different_exits_2_const_compare_known(
530
+ ; CHECK-SAME: ptr [[S:%.*]], i1 [[C_1:%.*]], i1 [[C_2:%.*]]) {
531
+ ; CHECK-NEXT: [[ENTRY:.*]]:
532
+ ; CHECK-NEXT: br label %[[LOOP_HEADER:.*]]
533
+ ; CHECK: [[LOOP_HEADER]]:
534
+ ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
535
+ ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[IV]], 1234
536
+ ; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[EXIT_1:.*]], label %[[ELSE_1:.*]]
537
+ ; CHECK: [[ELSE_1]]:
538
+ ; CHECK-NEXT: br i1 [[C_1]], label %[[EXIT_1]], label %[[ELSE_2:.*]]
539
+ ; CHECK: [[ELSE_2]]:
540
+ ; CHECK-NEXT: br i1 [[C_2]], label %[[EXIT_2:.*]], label %[[LOOP_LATCH]]
541
+ ; CHECK: [[LOOP_LATCH]]:
542
+ ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]]
543
+ ; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1
544
+ ; CHECK-NEXT: [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10
545
+ ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
546
+ ; CHECK-NEXT: br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT_2]]
547
+ ; CHECK: [[EXIT_1]]:
548
+ ; CHECK-NEXT: [[T_1:%.*]] = icmp ult i32 [[IV]], 1235
549
+ ; CHECK-NEXT: ret i1 [[T_1]]
550
+ ; CHECK: [[EXIT_2]]:
551
+ ; CHECK-NEXT: ret i1 true
552
+ ;
553
+ entry:
554
+ br label %loop.header
555
+
556
+ loop.header:
557
+ %iv = phi i32 [ 0 , %entry ], [ %iv.next , %loop.latch ]
558
+ %exitcond.not = icmp eq i32 %iv , 1234
559
+ br i1 %exitcond.not , label %exit.1 , label %else.1
560
+
561
+ else.1 :
562
+ br i1 %c.1 , label %exit.1 , label %else.2
563
+
564
+ else.2 :
565
+ br i1 %c.2 , label %exit.2 , label %loop.latch
566
+
567
+ loop.latch:
568
+ %arrayidx = getelementptr inbounds i8 , ptr %s , i32 %iv
569
+ %0 = load i8 , ptr %arrayidx , align 1
570
+ %latch.c = icmp ult i8 %0 , 10
571
+ %iv.next = add nuw nsw i32 %iv , 1
572
+ br i1 %latch.c , label %loop.header , label %exit.2
573
+
574
+ exit.1 :
575
+ %t.1 = icmp ult i32 %iv , 1235
576
+ ret i1 %t.1
577
+
578
+ exit.2 :
579
+ %t.2 = icmp ult i32 %iv , 1235
580
+ ret i1 %t.2
581
+ }
582
+
583
+
584
+ define i1 @multi_exiting_loop_eq_different_exits_compare_not_known (ptr %s , i32 %N ) {
585
+ ; CHECK-LABEL: define i1 @multi_exiting_loop_eq_different_exits_compare_not_known(
586
+ ; CHECK-SAME: ptr [[S:%.*]], i32 [[N:%.*]]) {
587
+ ; CHECK-NEXT: [[ENTRY:.*]]:
588
+ ; CHECK-NEXT: br label %[[LOOP_HEADER:.*]]
589
+ ; CHECK: [[LOOP_HEADER]]:
590
+ ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
591
+ ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[IV]], [[N]]
592
+ ; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[EXIT_1:.*]], label %[[LOOP_LATCH]]
593
+ ; CHECK: [[LOOP_LATCH]]:
594
+ ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]]
595
+ ; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1
596
+ ; CHECK-NEXT: [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10
597
+ ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
598
+ ; CHECK-NEXT: br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT_2:.*]]
599
+ ; CHECK: [[EXIT_1]]:
600
+ ; CHECK-NEXT: ret i1 false
601
+ ; CHECK: [[EXIT_2]]:
602
+ ; CHECK-NEXT: ret i1 true
603
+ ;
604
+ entry:
605
+ br label %loop.header
484
606
607
+ loop.header:
608
+ %iv = phi i32 [ 0 , %entry ], [ %iv.next , %loop.latch ]
609
+ %exitcond.not = icmp eq i32 %iv , %N
610
+ br i1 %exitcond.not , label %exit.1 , label %loop.latch
611
+
612
+ loop.latch:
613
+ %arrayidx = getelementptr inbounds i8 , ptr %s , i32 %iv
614
+ %0 = load i8 , ptr %arrayidx , align 1
615
+ %latch.c = icmp ult i8 %0 , 10
616
+ %iv.next = add nuw nsw i32 %iv , 1
617
+ br i1 %latch.c , label %loop.header , label %exit.2
618
+
619
+ exit.1 :
620
+ %t.1 = icmp ult i32 %iv , %N
621
+ ret i1 %t.1
622
+
623
+ exit.2 :
624
+ %t.2 = icmp ult i32 %iv , %N
625
+ ret i1 %t.2
626
+ }
627
+
628
+ define i1 @multi_exiting_loop_eq_different_exits_2_compare_not_known (ptr %s , i32 %N , i1 %c.1 , i1 %c.2 ) {
629
+ ; CHECK-LABEL: define i1 @multi_exiting_loop_eq_different_exits_2_compare_not_known(
630
+ ; CHECK-SAME: ptr [[S:%.*]], i32 [[N:%.*]], i1 [[C_1:%.*]], i1 [[C_2:%.*]]) {
631
+ ; CHECK-NEXT: [[ENTRY:.*]]:
632
+ ; CHECK-NEXT: br label %[[LOOP_HEADER:.*]]
633
+ ; CHECK: [[LOOP_HEADER]]:
634
+ ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
635
+ ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[IV]], [[N]]
636
+ ; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[EXIT_1:.*]], label %[[ELSE_1:.*]]
637
+ ; CHECK: [[ELSE_1]]:
638
+ ; CHECK-NEXT: br i1 [[C_1]], label %[[EXIT_1]], label %[[ELSE_2:.*]]
639
+ ; CHECK: [[ELSE_2]]:
640
+ ; CHECK-NEXT: br i1 [[C_2]], label %[[EXIT_2:.*]], label %[[LOOP_LATCH]]
641
+ ; CHECK: [[LOOP_LATCH]]:
642
+ ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]]
643
+ ; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1
644
+ ; CHECK-NEXT: [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10
645
+ ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
646
+ ; CHECK-NEXT: br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT_2]]
647
+ ; CHECK: [[EXIT_1]]:
648
+ ; CHECK-NEXT: [[T_1:%.*]] = icmp ult i32 [[IV]], [[N]]
649
+ ; CHECK-NEXT: ret i1 [[T_1]]
650
+ ; CHECK: [[EXIT_2]]:
651
+ ; CHECK-NEXT: ret i1 true
652
+ ;
653
+ entry:
654
+ br label %loop.header
655
+
656
+ loop.header:
657
+ %iv = phi i32 [ 0 , %entry ], [ %iv.next , %loop.latch ]
658
+ %exitcond.not = icmp eq i32 %iv , %N
659
+ br i1 %exitcond.not , label %exit.1 , label %else.1
660
+
661
+ else.1 :
662
+ br i1 %c.1 , label %exit.1 , label %else.2
663
+
664
+ else.2 :
665
+ br i1 %c.2 , label %exit.2 , label %loop.latch
666
+
667
+ loop.latch:
668
+ %arrayidx = getelementptr inbounds i8 , ptr %s , i32 %iv
669
+ %0 = load i8 , ptr %arrayidx , align 1
670
+ %latch.c = icmp ult i8 %0 , 10
671
+ %iv.next = add nuw nsw i32 %iv , 1
672
+ br i1 %latch.c , label %loop.header , label %exit.2
673
+
674
+ exit.1 :
675
+ %t.1 = icmp ult i32 %iv , %N
676
+ ret i1 %t.1
677
+
678
+ exit.2 :
679
+ %t.2 = icmp ult i32 %iv , %N
680
+ ret i1 %t.2
681
+ }
682
+
683
+ define i1 @multi_exiting_loop_ne_different_exits_const_compare_known (ptr %s ) {
684
+ ; CHECK-LABEL: define i1 @multi_exiting_loop_ne_different_exits_const_compare_known(
685
+ ; CHECK-SAME: ptr [[S:%.*]]) {
686
+ ; CHECK-NEXT: [[ENTRY:.*]]:
687
+ ; CHECK-NEXT: br label %[[LOOP_HEADER:.*]]
688
+ ; CHECK: [[LOOP_HEADER]]:
689
+ ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 1, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
690
+ ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp ne i32 [[IV]], 1234
691
+ ; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[LOOP_LATCH]], label %[[EXIT_1:.*]]
692
+ ; CHECK: [[LOOP_LATCH]]:
693
+ ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]]
694
+ ; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1
695
+ ; CHECK-NEXT: [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10
696
+ ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
697
+ ; CHECK-NEXT: br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT_2:.*]]
698
+ ; CHECK: [[EXIT_1]]:
699
+ ; CHECK-NEXT: ret i1 true
700
+ ; CHECK: [[EXIT_2]]:
701
+ ; CHECK-NEXT: ret i1 true
702
+ ;
703
+ entry:
704
+ br label %loop.header
705
+
706
+ loop.header:
707
+ %iv = phi i32 [ 1 , %entry ], [ %iv.next , %loop.latch ]
708
+ %exitcond.not = icmp ne i32 %iv , 1234
709
+ br i1 %exitcond.not , label %loop.latch , label %exit.1
710
+
711
+ loop.latch:
712
+ %arrayidx = getelementptr inbounds i8 , ptr %s , i32 %iv
713
+ %0 = load i8 , ptr %arrayidx , align 1
714
+ %latch.c = icmp ult i8 %0 , 10
715
+ %iv.next = add nuw nsw i32 %iv , 1
716
+ br i1 %latch.c , label %loop.header , label %exit.2
717
+
718
+ exit.1 :
719
+ %t.1 = icmp ult i32 %iv , 1235
720
+ ret i1 %t.1
721
+
722
+ exit.2 :
723
+ %t.2 = icmp ult i32 %iv , 1235
724
+ ret i1 %t.2
725
+ }
726
+
727
+ define i1 @multi_exiting_loop_ne_different_exits_compare_not_known (ptr %s , i32 %N ) {
728
+ ; CHECK-LABEL: define i1 @multi_exiting_loop_ne_different_exits_compare_not_known(
729
+ ; CHECK-SAME: ptr [[S:%.*]], i32 [[N:%.*]]) {
730
+ ; CHECK-NEXT: [[ENTRY:.*]]:
731
+ ; CHECK-NEXT: br label %[[LOOP_HEADER:.*]]
732
+ ; CHECK: [[LOOP_HEADER]]:
733
+ ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 1, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
734
+ ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp ne i32 [[IV]], [[N]]
735
+ ; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[LOOP_LATCH]], label %[[EXIT_1:.*]]
736
+ ; CHECK: [[LOOP_LATCH]]:
737
+ ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]]
738
+ ; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1
739
+ ; CHECK-NEXT: [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10
740
+ ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
741
+ ; CHECK-NEXT: br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT_2:.*]]
742
+ ; CHECK: [[EXIT_1]]:
743
+ ; CHECK-NEXT: ret i1 false
744
+ ; CHECK: [[EXIT_2]]:
745
+ ; CHECK-NEXT: [[T_2:%.*]] = icmp ult i32 [[IV]], [[N]]
746
+ ; CHECK-NEXT: ret i1 [[T_2]]
747
+ ;
748
+ entry:
749
+ br label %loop.header
750
+
751
+ loop.header:
752
+ %iv = phi i32 [ 1 , %entry ], [ %iv.next , %loop.latch ]
753
+ %exitcond.not = icmp ne i32 %iv , %N
754
+ br i1 %exitcond.not , label %loop.latch , label %exit.1
755
+
756
+ loop.latch:
757
+ %arrayidx = getelementptr inbounds i8 , ptr %s , i32 %iv
758
+ %0 = load i8 , ptr %arrayidx , align 1
759
+ %latch.c = icmp ult i8 %0 , 10
760
+ %iv.next = add nuw nsw i32 %iv , 1
761
+ br i1 %latch.c , label %loop.header , label %exit.2
762
+
763
+ exit.1 :
764
+ %t.1 = icmp ult i32 %iv , %N
765
+ ret i1 %t.1
766
+
767
+ exit.2 :
768
+ %t.2 = icmp ult i32 %iv , %N
769
+ ret i1 %t.2
770
+ }
0 commit comments