1; RUN: opt -loop-vectorize -mtriple=arm64-apple-iphoneos -vectorizer-min-trip-count=8 -S %s | FileCheck --check-prefixes=CHECK,DEFAULT %s 2; RUN: opt -loop-vectorize -mtriple=arm64-apple-iphoneos -vectorizer-min-trip-count=8 -vectorize-memory-check-threshold=1 -S %s | FileCheck --check-prefixes=CHECK,THRESHOLD %s 3 4; Tests for loops with large numbers of runtime checks. Check that loops are 5; vectorized, if the loop trip counts are large and the impact of the runtime 6; checks is very small compared to the expected loop runtimes. 7 8 9; The trip count in the loop in this function is too to warrant large runtime checks. 10; CHECK-LABEL: define {{.*}} @test_tc_too_small 11; CHECK-NOT: vector.memcheck 12; CHECK-NOT: vector.body 13define void @test_tc_too_small(i16* %ptr.1, i16* %ptr.2, i16* %ptr.3, i16* %ptr.4, i64 %off.1, i64 %off.2) { 14entry: 15 br label %loop 16 17loop: ; preds = %bb54, %bb37 18 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] 19 %gep.1 = getelementptr inbounds i16, i16* %ptr.1, i64 %iv 20 %lv.1 = load i16, i16* %gep.1, align 2 21 %ext.1 = sext i16 %lv.1 to i32 22 %gep.2 = getelementptr inbounds i16, i16* %ptr.2, i64 %iv 23 %lv.2 = load i16, i16* %gep.2, align 2 24 %ext.2 = sext i16 %lv.2 to i32 25 %gep.off.1 = getelementptr inbounds i16, i16* %gep.2, i64 %off.1 26 %lv.3 = load i16, i16* %gep.off.1, align 2 27 %ext.3 = sext i16 %lv.3 to i32 28 %gep.off.2 = getelementptr inbounds i16, i16* %gep.2, i64 %off.2 29 %lv.4 = load i16, i16* %gep.off.2, align 2 30 %ext.4 = sext i16 %lv.4 to i32 31 %tmp62 = mul nsw i32 %ext.2, 11 32 %tmp66 = mul nsw i32 %ext.3, -4 33 %tmp70 = add nsw i32 %tmp62, 4 34 %tmp71 = add nsw i32 %tmp70, %tmp66 35 %tmp72 = add nsw i32 %tmp71, %ext.4 36 %tmp73 = lshr i32 %tmp72, 3 37 %tmp74 = add nsw i32 %tmp73, %ext.1 38 %tmp75 = lshr i32 %tmp74, 1 39 %tmp76 = mul nsw i32 %ext.2, 5 40 %tmp77 = shl nsw i32 %ext.3, 2 41 %tmp78 = add nsw i32 %tmp76, 4 42 %tmp79 = add nsw i32 %tmp78, %tmp77 43 %tmp80 = sub nsw i32 %tmp79, %ext.4 44 %tmp81 = lshr i32 %tmp80, 3 45 %tmp82 = sub nsw i32 %tmp81, %ext.1 46 %tmp83 = lshr i32 %tmp82, 1 47 %trunc.1 = trunc i32 %tmp75 to i16 48 %gep.3 = getelementptr inbounds i16, i16* %ptr.3, i64 %iv 49 store i16 %trunc.1, i16* %gep.3, align 2 50 %trunc.2 = trunc i32 %tmp83 to i16 51 %gep.4 = getelementptr inbounds i16, i16* %ptr.4, i64 %iv 52 store i16 %trunc.2, i16* %gep.4, align 2 53 %iv.next = add nuw nsw i64 %iv, 1 54 %cmp = icmp ult i64 %iv, 10 55 br i1 %cmp, label %loop, label %exit 56 57exit: 58 ret void 59} 60 61; The trip count in the loop in this function high enough to warrant large runtime checks. 62; CHECK-LABEL: define {{.*}} @test_tc_big_enough 63; DEFAULT: vector.memcheck 64; DEFAULT: vector.body 65; THRESHOLD-NOT: vector.memcheck 66; THRESHOLD-NOT: vector.body 67; 68define void @test_tc_big_enough(i16* %ptr.1, i16* %ptr.2, i16* %ptr.3, i16* %ptr.4, i64 %off.1, i64 %off.2) { 69entry: 70 br label %loop 71 72loop: ; preds = %bb54, %bb37 73 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] 74 %gep.1 = getelementptr inbounds i16, i16* %ptr.1, i64 %iv 75 %lv.1 = load i16, i16* %gep.1, align 2 76 %ext.1 = sext i16 %lv.1 to i32 77 %gep.2 = getelementptr inbounds i16, i16* %ptr.2, i64 %iv 78 %lv.2 = load i16, i16* %gep.2, align 2 79 %ext.2 = sext i16 %lv.2 to i32 80 %gep.off.1 = getelementptr inbounds i16, i16* %gep.2, i64 %off.1 81 %lv.3 = load i16, i16* %gep.off.1, align 2 82 %ext.3 = sext i16 %lv.3 to i32 83 %gep.off.2 = getelementptr inbounds i16, i16* %gep.2, i64 %off.2 84 %lv.4 = load i16, i16* %gep.off.2, align 2 85 %ext.4 = sext i16 %lv.4 to i32 86 %tmp62 = mul nsw i32 %ext.2, 11 87 %tmp66 = mul nsw i32 %ext.3, -4 88 %tmp70 = add nsw i32 %tmp62, 4 89 %tmp71 = add nsw i32 %tmp70, %tmp66 90 %tmp72 = add nsw i32 %tmp71, %ext.4 91 %tmp73 = lshr i32 %tmp72, 3 92 %tmp74 = add nsw i32 %tmp73, %ext.1 93 %tmp75 = lshr i32 %tmp74, 1 94 %tmp76 = mul nsw i32 %ext.2, 5 95 %tmp77 = shl nsw i32 %ext.3, 2 96 %tmp78 = add nsw i32 %tmp76, 4 97 %tmp79 = add nsw i32 %tmp78, %tmp77 98 %tmp80 = sub nsw i32 %tmp79, %ext.4 99 %tmp81 = lshr i32 %tmp80, 3 100 %tmp82 = sub nsw i32 %tmp81, %ext.1 101 %tmp83 = lshr i32 %tmp82, 1 102 %trunc.1 = trunc i32 %tmp75 to i16 103 %gep.3 = getelementptr inbounds i16, i16* %ptr.3, i64 %iv 104 store i16 %trunc.1, i16* %gep.3, align 2 105 %trunc.2 = trunc i32 %tmp83 to i16 106 %gep.4 = getelementptr inbounds i16, i16* %ptr.4, i64 %iv 107 store i16 %trunc.2, i16* %gep.4, align 2 108 %iv.next = add nuw nsw i64 %iv, 1 109 %cmp = icmp ult i64 %iv, 500 110 br i1 %cmp, label %loop, label %exit 111 112exit: 113 ret void 114} 115 116define void @test_tc_unknown(i16* %ptr.1, i16* %ptr.2, i16* %ptr.3, i16* %ptr.4, i64 %off.1, i64 %off.2, i64 %N) { 117; CHECK-LABEL: define void @test_tc_unknown 118; DEFAULT: [[ADD:%.+]] = add i64 %N, 1 119; DEFAULT-NEXT: [[C:%.+]] = icmp ult i64 [[ADD]], 16 120; DEFAULT-NEXT: br i1 [[C]], label %scalar.ph, label %vector.memcheck 121; THRESHOLD-NOT: vector.memcheck 122; THRESHOLD-NOT: vector.body 123; 124entry: 125 br label %loop 126 127loop: ; preds = %bb54, %bb37 128 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] 129 %gep.1 = getelementptr inbounds i16, i16* %ptr.1, i64 %iv 130 %lv.1 = load i16, i16* %gep.1, align 2 131 %ext.1 = sext i16 %lv.1 to i32 132 %gep.2 = getelementptr inbounds i16, i16* %ptr.2, i64 %iv 133 %lv.2 = load i16, i16* %gep.2, align 2 134 %ext.2 = sext i16 %lv.2 to i32 135 %gep.off.1 = getelementptr inbounds i16, i16* %gep.2, i64 %off.1 136 %lv.3 = load i16, i16* %gep.off.1, align 2 137 %ext.3 = sext i16 %lv.3 to i32 138 %gep.off.2 = getelementptr inbounds i16, i16* %gep.2, i64 %off.2 139 %lv.4 = load i16, i16* %gep.off.2, align 2 140 %ext.4 = sext i16 %lv.4 to i32 141 %tmp62 = mul nsw i32 %ext.2, 11 142 %tmp66 = mul nsw i32 %ext.3, -4 143 %tmp70 = add nsw i32 %tmp62, 4 144 %tmp71 = add nsw i32 %tmp70, %tmp66 145 %tmp72 = add nsw i32 %tmp71, %ext.4 146 %tmp73 = lshr i32 %tmp72, 3 147 %tmp74 = add nsw i32 %tmp73, %ext.1 148 %tmp75 = lshr i32 %tmp74, 1 149 %tmp76 = mul nsw i32 %ext.2, 5 150 %tmp77 = shl nsw i32 %ext.3, 2 151 %tmp78 = add nsw i32 %tmp76, 4 152 %tmp79 = add nsw i32 %tmp78, %tmp77 153 %tmp80 = sub nsw i32 %tmp79, %ext.4 154 %tmp81 = lshr i32 %tmp80, 3 155 %tmp82 = sub nsw i32 %tmp81, %ext.1 156 %tmp83 = lshr i32 %tmp82, 1 157 %trunc.1 = trunc i32 %tmp75 to i16 158 %gep.3 = getelementptr inbounds i16, i16* %ptr.3, i64 %iv 159 store i16 %trunc.1, i16* %gep.3, align 2 160 %trunc.2 = trunc i32 %tmp83 to i16 161 %gep.4 = getelementptr inbounds i16, i16* %ptr.4, i64 %iv 162 store i16 %trunc.2, i16* %gep.4, align 2 163 %iv.next = add nuw nsw i64 %iv, 1 164 %cmp = icmp ult i64 %iv, %N 165 br i1 %cmp, label %loop, label %exit 166 167exit: 168 ret void 169} 170