@@ -470,6 +470,192 @@ loop.end:
470470 ret i64 %retval
471471}
472472
473+ define void @loop_contains_store_single_user (ptr dereferenceable (40 ) noalias %array , ptr align 2 dereferenceable (40 ) readonly %pred ) {
474+ ; CHECK-LABEL: LV: Checking a loop in 'loop_contains_store_single_user'
475+ ; CHECK: LV: Not vectorizing: Writes to memory unsupported in early exit loops.
476+ entry:
477+ br label %for.body
478+
479+ for.body:
480+ %iv = phi i64 [ 0 , %entry ], [ %iv.next , %for.inc ]
481+ %st.addr = getelementptr inbounds nuw i16 , ptr %array , i64 %iv
482+ %data = load i16 , ptr %st.addr , align 2
483+ %inc = add nsw i16 %data , 1
484+ store i16 %inc , ptr %st.addr , align 2
485+ %ee.addr = getelementptr inbounds nuw i16 , ptr %pred , i64 %iv
486+ %ee.val = load i16 , ptr %ee.addr , align 2
487+ %ee.cond = icmp sgt i16 %ee.val , 500
488+ br i1 %ee.cond , label %exit , label %for.inc
489+
490+ for.inc:
491+ %iv.next = add nuw nsw i64 %iv , 1
492+ %counted.cond = icmp eq i64 %iv.next , 20
493+ br i1 %counted.cond , label %exit , label %for.body
494+
495+ exit:
496+ ret void
497+ }
498+
499+ define void @loop_contains_store_multi_user (ptr dereferenceable (40 ) noalias %array , ptr align 2 dereferenceable (40 ) readonly %pred ) {
500+ ; CHECK-LABEL: LV: Checking a loop in 'loop_contains_store_multi_user'
501+ ; CHECK: LV: Not vectorizing: Writes to memory unsupported in early exit loops.
502+ entry:
503+ br label %for.body
504+
505+ for.body:
506+ %iv = phi i64 [ 0 , %entry ], [ %iv.next , %for.inc ]
507+ %st.addr = getelementptr inbounds nuw i16 , ptr %array , i64 %iv
508+ %data = load i16 , ptr %st.addr , align 2
509+ %inc = add nsw i16 %data , 1
510+ store i16 %inc , ptr %st.addr , align 2
511+ %ee.addr = getelementptr inbounds nuw i16 , ptr %pred , i64 %iv
512+ %ee.val = load i16 , ptr %ee.addr , align 2
513+ %ee.cond = icmp sgt i16 %ee.val , 500
514+ %unused = add i16 %ee.val , 42
515+ br i1 %ee.cond , label %exit , label %for.inc
516+
517+ for.inc:
518+ %iv.next = add nuw nsw i64 %iv , 1
519+ %counted.cond = icmp eq i64 %iv.next , 20
520+ br i1 %counted.cond , label %exit , label %for.body
521+
522+ exit:
523+ ret void
524+ }
525+
526+ define void @loop_contains_store_fcmp (ptr dereferenceable (40 ) noalias %array , ptr align 2 dereferenceable (40 ) readonly %pred ) {
527+ ; CHECK-LABEL: LV: Checking a loop in 'loop_contains_store_fcmp'
528+ ; CHECK: LV: Not vectorizing: Writes to memory unsupported in early exit loops.
529+ entry:
530+ br label %for.body
531+
532+ for.body:
533+ %iv = phi i64 [ 0 , %entry ], [ %iv.next , %for.inc ]
534+ %st.addr = getelementptr inbounds nuw i16 , ptr %array , i64 %iv
535+ %data = load i16 , ptr %st.addr , align 2
536+ %inc = add nsw i16 %data , 1
537+ store i16 %inc , ptr %st.addr , align 2
538+ %ee.addr = getelementptr inbounds nuw half , ptr %pred , i64 %iv
539+ %ee.val = load half , ptr %ee.addr , align 2
540+ %ee.cond = fcmp ugt half %ee.val , 500 .0
541+ br i1 %ee.cond , label %exit , label %for.inc
542+
543+ for.inc:
544+ %iv.next = add nuw nsw i64 %iv , 1
545+ %counted.cond = icmp eq i64 %iv.next , 20
546+ br i1 %counted.cond , label %exit , label %for.body
547+
548+ exit:
549+ ret void
550+ }
551+
552+ define void @loop_contains_store_safe_dependency (ptr dereferenceable (40 ) noalias %array , ptr align 2 dereferenceable (80 ) readonly %pred ) {
553+ ; CHECK-LABEL: LV: Checking a loop in 'loop_contains_store_safe_dependency'
554+ ; CHECK: LV: Not vectorizing: Writes to memory unsupported in early exit loops.
555+ entry:
556+ %forward = getelementptr i16 , ptr %pred , i64 -8
557+ br label %for.body
558+
559+ for.body:
560+ %iv = phi i64 [ 0 , %entry ], [ %iv.next , %for.inc ]
561+ %st.addr = getelementptr inbounds nuw i16 , ptr %array , i64 %iv
562+ %data = load i16 , ptr %st.addr , align 2
563+ %inc = add nsw i16 %data , 1
564+ store i16 %inc , ptr %st.addr , align 2
565+ %ee.addr = getelementptr inbounds nuw i16 , ptr %pred , i64 %iv
566+ %ee.val = load i16 , ptr %ee.addr , align 2
567+ %ee.cond = icmp sgt i16 %ee.val , 500
568+ %some.addr = getelementptr inbounds nuw i16 , ptr %forward , i64 %iv
569+ store i16 42 , ptr %some.addr , align 2
570+ br i1 %ee.cond , label %exit , label %for.inc
571+
572+ for.inc:
573+ %iv.next = add nuw nsw i64 %iv , 1
574+ %counted.cond = icmp eq i64 %iv.next , 20
575+ br i1 %counted.cond , label %exit , label %for.body
576+
577+ exit:
578+ ret void
579+ }
580+
581+ define void @loop_contains_store_assumed_bounds (ptr noalias %array , ptr readonly %pred , i32 %n ) {
582+ ; CHECK-LABEL: LV: Checking a loop in 'loop_contains_store_assumed_bounds'
583+ ; CHECK: LV: Not vectorizing: Writes to memory unsupported in early exit loops.
584+ entry:
585+ %n_bytes = mul nuw nsw i32 %n , 2
586+ call void @llvm.assume (i1 true ) [ "align" (ptr %pred , i64 2 ), "dereferenceable" (ptr %pred , i32 %n_bytes ) ]
587+ %tc = sext i32 %n to i64
588+ br label %for.body
589+
590+ for.body:
591+ %iv = phi i64 [ 0 , %entry ], [ %iv.next , %for.inc ]
592+ %st.addr = getelementptr inbounds nuw i16 , ptr %array , i64 %iv
593+ %data = load i16 , ptr %st.addr , align 2
594+ %inc = add nsw i16 %data , 1
595+ store i16 %inc , ptr %st.addr , align 2
596+ %ee.addr = getelementptr inbounds nuw i16 , ptr %pred , i64 %iv
597+ %ee.val = load i16 , ptr %ee.addr , align 2
598+ %ee.cond = icmp sgt i16 %ee.val , 500
599+ br i1 %ee.cond , label %exit , label %for.inc
600+
601+ for.inc:
602+ %iv.next = add nuw nsw i64 %iv , 1
603+ %counted.cond = icmp eq i64 %iv.next , %tc
604+ br i1 %counted.cond , label %exit , label %for.body
605+
606+ exit:
607+ ret void
608+ }
609+
610+ define void @loop_contains_store_volatile (ptr dereferenceable (40 ) noalias %array , ptr align 2 dereferenceable (40 ) readonly %pred ) {
611+ ; CHECK-LABEL: LV: Checking a loop in 'loop_contains_store_volatile'
612+ ; CHECK: LV: Not vectorizing: Writes to memory unsupported in early exit loops.
613+ entry:
614+ br label %for.body
615+
616+ for.body:
617+ %iv = phi i64 [ 0 , %entry ], [ %iv.next , %for.inc ]
618+ %st.addr = getelementptr inbounds nuw i16 , ptr %array , i64 %iv
619+ %data = load i16 , ptr %st.addr , align 2
620+ %inc = add nsw i16 %data , 1
621+ store volatile i16 %inc , ptr %st.addr , align 2
622+ %ee.addr = getelementptr inbounds nuw i16 , ptr %pred , i64 %iv
623+ %ee.val = load i16 , ptr %ee.addr , align 2
624+ %ee.cond = icmp sgt i16 %ee.val , 500
625+ br i1 %ee.cond , label %exit , label %for.inc
626+
627+ for.inc:
628+ %iv.next = add nuw nsw i64 %iv , 1
629+ %counted.cond = icmp eq i64 %iv.next , 20
630+ br i1 %counted.cond , label %exit , label %for.body
631+
632+ exit:
633+ ret void
634+ }
635+
636+ define void @exit_conditions_combined (ptr noalias dereferenceable (40 ) %array , ptr readonly align 2 dereferenceable (40 ) %pred ) {
637+ ; CHECK-LABEL: LV: Checking a loop in 'exit_conditions_combined'
638+ ; CHECK: LV: Not vectorizing: Cannot vectorize uncountable loop.
639+ entry:
640+ br label %for.body
641+
642+ for.body: ; preds = %for.body, %entry
643+ %iv = phi i64 [ 0 , %entry ], [ %iv.next , %for.body ]
644+ %st.addr = getelementptr inbounds nuw i16 , ptr %array , i64 %iv
645+ %data = load i16 , ptr %st.addr , align 2
646+ %inc = add nsw i16 %data , 1
647+ store i16 %inc , ptr %st.addr , align 2
648+ %ee.addr = getelementptr inbounds nuw i16 , ptr %pred , i64 %iv
649+ %ee.val = load i16 , ptr %ee.addr , align 2
650+ %ee.cond = icmp sgt i16 %ee.val , 500
651+ %iv.next = add nuw nsw i64 %iv , 1
652+ %counted.cond = icmp eq i64 %iv.next , 20
653+ %or.cond = select i1 %ee.cond , i1 true , i1 %counted.cond
654+ br i1 %or.cond , label %exit , label %for.body
655+
656+ exit: ; preds = %for.body
657+ ret void
658+ }
473659
474660define i64 @uncountable_exit_in_conditional_block (ptr %mask ) {
475661; CHECK-LABEL: LV: Checking a loop in 'uncountable_exit_in_conditional_block'
0 commit comments