1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 2; RUN: opt -S < %s -p loop-vectorize -enable-early-exit-vectorization | FileCheck %s 3 4declare void @init_mem(ptr, i64); 5 6; There are multiple exit blocks - two of them have an exact representation for the 7; exit-not-taken counts and the other is unknown, i.e. the "early exit". 8define i64 @one_uncountable_two_countable_same_exit() { 9; CHECK-LABEL: define i64 @one_uncountable_two_countable_same_exit() { 10; CHECK-NEXT: entry: 11; CHECK-NEXT: [[P1:%.*]] = alloca [1024 x i8], align 1 12; CHECK-NEXT: [[P2:%.*]] = alloca [1024 x i8], align 1 13; CHECK-NEXT: call void @init_mem(ptr [[P1]], i64 1024) 14; CHECK-NEXT: call void @init_mem(ptr [[P2]], i64 1024) 15; CHECK-NEXT: br label [[LOOP:%.*]] 16; CHECK: loop: 17; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[LOOP_INC:%.*]] ], [ 3, [[ENTRY:%.*]] ] 18; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i64 [[INDEX]], 64 19; CHECK-NEXT: br i1 [[CMP1]], label [[SEARCH:%.*]], label [[LOOP_END:%.*]] 20; CHECK: search: 21; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[INDEX]] 22; CHECK-NEXT: [[LD1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 23; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 [[INDEX]] 24; CHECK-NEXT: [[LD2:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1 25; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i8 [[LD1]], [[LD2]] 26; CHECK-NEXT: br i1 [[CMP3]], label [[LOOP_END]], label [[LOOP_INC]] 27; CHECK: loop.inc: 28; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 1 29; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], 128 30; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LOOP_END]] 31; CHECK: loop.end: 32; CHECK-NEXT: [[RETVAL:%.*]] = phi i64 [ 64, [[LOOP]] ], [ [[INDEX]], [[SEARCH]] ], [ 128, [[LOOP_INC]] ] 33; CHECK-NEXT: ret i64 [[RETVAL]] 34; 35entry: 36 %p1 = alloca [1024 x i8] 37 %p2 = alloca [1024 x i8] 38 call void @init_mem(ptr %p1, i64 1024) 39 call void @init_mem(ptr %p2, i64 1024) 40 br label %loop 41 42loop: 43 %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ] 44 %cmp1 = icmp ne i64 %index, 64 45 br i1 %cmp1, label %search, label %loop.end 46 47search: 48 %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index 49 %ld1 = load i8, ptr %arrayidx, align 1 50 %arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index 51 %ld2 = load i8, ptr %arrayidx1, align 1 52 %cmp3 = icmp eq i8 %ld1, %ld2 53 br i1 %cmp3, label %loop.end, label %loop.inc 54 55loop.inc: 56 %index.next = add i64 %index, 1 57 %exitcond = icmp ne i64 %index.next, 128 58 br i1 %exitcond, label %loop, label %loop.end 59 60loop.end: 61 %retval = phi i64 [ 64, %loop ], [ %index, %search ], [ 128, %loop.inc ] 62 ret i64 %retval 63} 64 65 66define i64 @one_uncountable_two_countable_diff_exit() { 67; CHECK-LABEL: define i64 @one_uncountable_two_countable_diff_exit() { 68; CHECK-NEXT: entry: 69; CHECK-NEXT: [[P1:%.*]] = alloca [1024 x i8], align 1 70; CHECK-NEXT: [[P2:%.*]] = alloca [1024 x i8], align 1 71; CHECK-NEXT: call void @init_mem(ptr [[P1]], i64 1024) 72; CHECK-NEXT: call void @init_mem(ptr [[P2]], i64 1024) 73; CHECK-NEXT: br label [[LOOP:%.*]] 74; CHECK: loop: 75; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[LOOP_INC:%.*]] ], [ 3, [[ENTRY:%.*]] ] 76; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i64 [[INDEX]], 64 77; CHECK-NEXT: br i1 [[CMP1]], label [[SEARCH:%.*]], label [[LOOP_END:%.*]] 78; CHECK: search: 79; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[INDEX]] 80; CHECK-NEXT: [[LD1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 81; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 [[INDEX]] 82; CHECK-NEXT: [[LD2:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1 83; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i8 [[LD1]], [[LD2]] 84; CHECK-NEXT: br i1 [[CMP3]], label [[LOOP_END_EARLY:%.*]], label [[LOOP_INC]] 85; CHECK: loop.inc: 86; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 1 87; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], 128 88; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LOOP_END]] 89; CHECK: loop.end.early: 90; CHECK-NEXT: [[RET_EARLY:%.*]] = phi i64 [ [[INDEX]], [[SEARCH]] ] 91; CHECK-NEXT: ret i64 [[RET_EARLY]] 92; CHECK: loop.end: 93; CHECK-NEXT: [[RETVAL:%.*]] = phi i64 [ 64, [[LOOP]] ], [ 128, [[LOOP_INC]] ] 94; CHECK-NEXT: ret i64 [[RETVAL]] 95; 96entry: 97 %p1 = alloca [1024 x i8] 98 %p2 = alloca [1024 x i8] 99 call void @init_mem(ptr %p1, i64 1024) 100 call void @init_mem(ptr %p2, i64 1024) 101 br label %loop 102 103loop: 104 %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ] 105 %cmp1 = icmp ne i64 %index, 64 106 br i1 %cmp1, label %search, label %loop.end 107 108search: 109 %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index 110 %ld1 = load i8, ptr %arrayidx, align 1 111 %arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index 112 %ld2 = load i8, ptr %arrayidx1, align 1 113 %cmp3 = icmp eq i8 %ld1, %ld2 114 br i1 %cmp3, label %loop.end.early, label %loop.inc 115 116loop.inc: 117 %index.next = add i64 %index, 1 118 %exitcond = icmp ne i64 %index.next, 128 119 br i1 %exitcond, label %loop, label %loop.end 120 121loop.end.early: 122 %ret.early = phi i64 [ %index, %search ] 123 ret i64 %ret.early 124 125loop.end: 126 %retval = phi i64 [ 64, %loop ], [ 128, %loop.inc ] 127 ret i64 %retval 128} 129