496 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals none --filter-out-after "vector.ph" --version 52; RUN: opt %s -passes=loop-vectorize -hoist-runtime-checks=false -force-vector-width=4 -force-vector-interleave=1 -S | FileCheck %s3 4target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"5 6define void @same_step_and_size(ptr %a, ptr %b, i64 %n) {7; CHECK-LABEL: define void @same_step_and_size(8; CHECK-SAME: ptr [[A:%.*]], ptr [[B:%.*]], i64 [[N:%.*]]) {9; CHECK-NEXT: [[ENTRY:.*:]]10; CHECK-NEXT: [[A2:%.*]] = ptrtoint ptr [[A]] to i6411; CHECK-NEXT: [[B1:%.*]] = ptrtoint ptr [[B]] to i6412; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[N]], 413; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], [[SCALAR_PH:label %.*]], label %[[VECTOR_MEMCHECK:.*]]14; CHECK: [[VECTOR_MEMCHECK]]:15; CHECK-NEXT: [[TMP0:%.*]] = sub i64 [[B1]], [[A2]]16; CHECK-NEXT: [[DIFF_CHECK:%.*]] = icmp ult i64 [[TMP0]], 1617; CHECK-NEXT: br i1 [[DIFF_CHECK]], [[SCALAR_PH]], [[VECTOR_PH:label %.*]]18;19entry:20 br label %loop21 22loop:23 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]24 %gep.a = getelementptr inbounds i32, ptr %a, i64 %iv25 %l = load i32, ptr %gep.a26 %mul = mul nsw i32 %l, 327 %gep.b = getelementptr inbounds i32, ptr %b, i64 %iv28 store i32 %mul, ptr %gep.b29 %iv.next = add nuw nsw i64 %iv, 130 %exitcond = icmp eq i64 %iv.next, %n31 br i1 %exitcond, label %exit, label %loop32 33exit:34 ret void35}36 37define void @same_step_and_size_no_dominance_between_accesses(ptr %a, ptr %b, i64 %n, i64 %x) {38; CHECK-LABEL: define void @same_step_and_size_no_dominance_between_accesses(39; CHECK-SAME: ptr [[A:%.*]], ptr [[B:%.*]], i64 [[N:%.*]], i64 [[X:%.*]]) {40; CHECK-NEXT: [[ENTRY:.*:]]41; CHECK-NEXT: [[B2:%.*]] = ptrtoint ptr [[B]] to i6442; CHECK-NEXT: [[A1:%.*]] = ptrtoint ptr [[A]] to i6443; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[N]], 444; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], [[SCALAR_PH:label %.*]], label %[[VECTOR_MEMCHECK:.*]]45; CHECK: [[VECTOR_MEMCHECK]]:46; CHECK-NEXT: [[TMP0:%.*]] = sub i64 [[A1]], [[B2]]47; CHECK-NEXT: [[DIFF_CHECK:%.*]] = icmp ult i64 [[TMP0]], 1648; CHECK-NEXT: br i1 [[DIFF_CHECK]], [[SCALAR_PH]], [[VECTOR_PH:label %.*]]49;50entry:51 br label %loop52 53loop:54 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]55 %cmp = icmp ne i64 %iv, %x56 br i1 %cmp, label %then, label %else57 58then:59 %gep.a = getelementptr inbounds i32, ptr %a, i64 %iv60 store i32 0, ptr %gep.a61 br label %loop.latch62 63else:64 %gep.b = getelementptr inbounds i32, ptr %b, i64 %iv65 store i32 10, ptr %gep.b66 br label %loop.latch67 68loop.latch:69 %iv.next = add nuw nsw i64 %iv, 170 %exitcond = icmp eq i64 %iv.next, %n71 br i1 %exitcond, label %exit, label %loop72 73exit:74 ret void75}76 77define void @different_steps_and_different_access_sizes(ptr %a, ptr %b, i64 %n) {78; CHECK-LABEL: define void @different_steps_and_different_access_sizes(79; CHECK-SAME: ptr [[A:%.*]], ptr [[B:%.*]], i64 [[N:%.*]]) {80; CHECK-NEXT: [[ENTRY:.*:]]81; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[N]], 482; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], [[SCALAR_PH:label %.*]], label %[[VECTOR_MEMCHECK:.*]]83; CHECK: [[VECTOR_MEMCHECK]]:84; CHECK-NEXT: [[TMP0:%.*]] = shl i64 [[N]], 285; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[B]], i64 [[TMP0]]86; CHECK-NEXT: [[TMP1:%.*]] = shl i64 [[N]], 187; CHECK-NEXT: [[SCEVGEP1:%.*]] = getelementptr i8, ptr [[A]], i64 [[TMP1]]88; CHECK-NEXT: [[BOUND0:%.*]] = icmp ult ptr [[B]], [[SCEVGEP1]]89; CHECK-NEXT: [[BOUND1:%.*]] = icmp ult ptr [[A]], [[SCEVGEP]]90; CHECK-NEXT: [[FOUND_CONFLICT:%.*]] = and i1 [[BOUND0]], [[BOUND1]]91; CHECK-NEXT: br i1 [[FOUND_CONFLICT]], [[SCALAR_PH]], [[VECTOR_PH:label %.*]]92;93entry:94 br label %loop95 96loop:97 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]98 %gep.a = getelementptr inbounds i16, ptr %a, i64 %iv99 %l = load i16, ptr %gep.a100 %l.ext = sext i16 %l to i32101 %mul = mul nsw i32 %l.ext, 3102 %gep.b = getelementptr inbounds i32, ptr %b, i64 %iv103 store i32 %mul, ptr %gep.b104 %iv.next = add nuw nsw i64 %iv, 1105 %exitcond = icmp eq i64 %iv.next, %n106 br i1 %exitcond, label %exit, label %loop107 108exit:109 ret void110}111 112define void @steps_match_but_different_access_sizes_1(ptr %a, ptr %b, i64 %n) {113; CHECK-LABEL: define void @steps_match_but_different_access_sizes_1(114; CHECK-SAME: ptr [[A:%.*]], ptr [[B:%.*]], i64 [[N:%.*]]) {115; CHECK-NEXT: [[ENTRY:.*:]]116; CHECK-NEXT: [[A2:%.*]] = ptrtoint ptr [[A]] to i64117; CHECK-NEXT: [[B1:%.*]] = ptrtoint ptr [[B]] to i64118; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[N]], 4119; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], [[SCALAR_PH:label %.*]], label %[[VECTOR_MEMCHECK:.*]]120; CHECK: [[VECTOR_MEMCHECK]]:121; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[B1]], -2122; CHECK-NEXT: [[TMP1:%.*]] = sub i64 [[TMP0]], [[A2]]123; CHECK-NEXT: [[DIFF_CHECK:%.*]] = icmp ult i64 [[TMP1]], 16124; CHECK-NEXT: br i1 [[DIFF_CHECK]], [[SCALAR_PH]], [[VECTOR_PH:label %.*]]125;126entry:127 br label %loop128 129loop:130 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]131 %gep.a = getelementptr inbounds [2 x i16], ptr %a, i64 %iv, i64 1132 %l = load i16, ptr %gep.a133 %l.ext = sext i16 %l to i32134 %mul = mul nsw i32 %l.ext, 3135 %gep.b = getelementptr inbounds i32, ptr %b, i64 %iv136 store i32 %mul, ptr %gep.b137 %iv.next = add nuw nsw i64 %iv, 1138 %exitcond = icmp eq i64 %iv.next, %n139 br i1 %exitcond, label %exit, label %loop140 141exit:142 ret void143}144 145; Same as @steps_match_but_different_access_sizes_1, but with source and sink146; accesses flipped.147define void @steps_match_but_different_access_sizes_2(ptr %a, ptr %b, i64 %n) {148; CHECK-LABEL: define void @steps_match_but_different_access_sizes_2(149; CHECK-SAME: ptr [[A:%.*]], ptr [[B:%.*]], i64 [[N:%.*]]) {150; CHECK-NEXT: [[ENTRY:.*:]]151; CHECK-NEXT: [[B2:%.*]] = ptrtoint ptr [[B]] to i64152; CHECK-NEXT: [[A1:%.*]] = ptrtoint ptr [[A]] to i64153; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[N]], 4154; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], [[SCALAR_PH:label %.*]], label %[[VECTOR_MEMCHECK:.*]]155; CHECK: [[VECTOR_MEMCHECK]]:156; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[A1]], 2157; CHECK-NEXT: [[TMP1:%.*]] = sub i64 [[TMP0]], [[B2]]158; CHECK-NEXT: [[DIFF_CHECK:%.*]] = icmp ult i64 [[TMP1]], 16159; CHECK-NEXT: br i1 [[DIFF_CHECK]], [[SCALAR_PH]], [[VECTOR_PH:label %.*]]160;161entry:162 br label %loop163 164loop:165 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]166 %gep.b = getelementptr inbounds i32, ptr %b, i64 %iv167 %l = load i32, ptr %gep.b168 %mul = mul nsw i32 %l, 3169 %gep.a = getelementptr inbounds [2 x i16], ptr %a, i64 %iv, i64 1170 %trunc = trunc i32 %mul to i16171 store i16 %trunc, ptr %gep.a172 %iv.next = add nuw nsw i64 %iv, 1173 %exitcond = icmp eq i64 %iv.next, %n174 br i1 %exitcond, label %exit, label %loop175 176exit:177 ret void178}179 180define void @steps_match_two_loadstores_different_access_sizes(ptr %src.1, ptr %src.2, ptr %dst.1, ptr %dst.2, i64 %n) {181; CHECK-LABEL: define void @steps_match_two_loadstores_different_access_sizes(182; CHECK-SAME: ptr [[SRC_1:%.*]], ptr [[SRC_2:%.*]], ptr [[DST_1:%.*]], ptr [[DST_2:%.*]], i64 [[N:%.*]]) {183; CHECK-NEXT: [[ENTRY:.*:]]184; CHECK-NEXT: [[SRC_25:%.*]] = ptrtoint ptr [[SRC_2]] to i64185; CHECK-NEXT: [[SRC_13:%.*]] = ptrtoint ptr [[SRC_1]] to i64186; CHECK-NEXT: [[DST_12:%.*]] = ptrtoint ptr [[DST_1]] to i64187; CHECK-NEXT: [[DST_21:%.*]] = ptrtoint ptr [[DST_2]] to i64188; CHECK-NEXT: [[UMAX:%.*]] = call i64 @llvm.umax.i64(i64 [[N]], i64 1)189; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[UMAX]], 4190; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], [[SCALAR_PH:label %.*]], label %[[VECTOR_MEMCHECK:.*]]191; CHECK: [[VECTOR_MEMCHECK]]:192; CHECK-NEXT: [[TMP0:%.*]] = sub i64 [[DST_21]], [[DST_12]]193; CHECK-NEXT: [[DIFF_CHECK:%.*]] = icmp ult i64 [[TMP0]], 32194; CHECK-NEXT: [[TMP1:%.*]] = sub i64 [[DST_12]], [[SRC_13]]195; CHECK-NEXT: [[DIFF_CHECK4:%.*]] = icmp ult i64 [[TMP1]], 32196; CHECK-NEXT: [[CONFLICT_RDX:%.*]] = or i1 [[DIFF_CHECK]], [[DIFF_CHECK4]]197; CHECK-NEXT: [[TMP2:%.*]] = sub i64 [[DST_12]], [[SRC_25]]198; CHECK-NEXT: [[DIFF_CHECK6:%.*]] = icmp ult i64 [[TMP2]], 32199; CHECK-NEXT: [[CONFLICT_RDX7:%.*]] = or i1 [[CONFLICT_RDX]], [[DIFF_CHECK6]]200; CHECK-NEXT: [[TMP3:%.*]] = sub i64 [[DST_21]], [[SRC_13]]201; CHECK-NEXT: [[DIFF_CHECK8:%.*]] = icmp ult i64 [[TMP3]], 32202; CHECK-NEXT: [[CONFLICT_RDX9:%.*]] = or i1 [[CONFLICT_RDX7]], [[DIFF_CHECK8]]203; CHECK-NEXT: [[TMP4:%.*]] = sub i64 [[DST_21]], [[SRC_25]]204; CHECK-NEXT: [[DIFF_CHECK10:%.*]] = icmp ult i64 [[TMP4]], 32205; CHECK-NEXT: [[CONFLICT_RDX11:%.*]] = or i1 [[CONFLICT_RDX9]], [[DIFF_CHECK10]]206; CHECK-NEXT: br i1 [[CONFLICT_RDX11]], [[SCALAR_PH]], [[VECTOR_PH:label %.*]]207;208entry:209 br label %loop210 211loop:212 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]213 %gep.src.1 = getelementptr i64, ptr %src.1, i64 %iv214 %ld.src.1 = load i64, ptr %gep.src.1215 %ld.src.1.i32 = trunc i64 %ld.src.1 to i32216 %gep.src.2 = getelementptr i64, ptr %src.2, i64 %iv217 %ld.src.2 = load i64, ptr %gep.src.2218 %add = add i64 %ld.src.1, %ld.src.2219 %gep.dst.1 = getelementptr nusw i64, ptr %dst.1, i64 %iv220 store i32 %ld.src.1.i32, ptr %gep.dst.1221 %gep.dst.2 = getelementptr nusw i64, ptr %dst.2, i64 %iv222 store i64 %add, ptr %gep.dst.2223 %iv.next = add nuw nsw i64 %iv, 1224 %cond = icmp ult i64 %iv.next, %n225 br i1 %cond, label %loop, label %exit226 227exit:228 ret void229}230 231; Full no-overlap checks are required instead of difference checks, as232; one of the add-recs used is invariant in the inner loop.233; Test case for PR57315.234define void @nested_loop_outer_iv_addrec_invariant_in_inner1(ptr %a, ptr %b, i64 %n) {235; CHECK-LABEL: define void @nested_loop_outer_iv_addrec_invariant_in_inner1(236; CHECK-SAME: ptr [[A:%.*]], ptr [[B:%.*]], i64 [[N:%.*]]) {237; CHECK-NEXT: [[ENTRY:.*]]:238; CHECK-NEXT: [[TMP0:%.*]] = shl i64 [[N]], 2239; CHECK-NEXT: [[SCEVGEP2:%.*]] = getelementptr i8, ptr [[B]], i64 [[TMP0]]240; CHECK-NEXT: br label %[[OUTER_HEADER:.*]]241; CHECK: [[OUTER_HEADER]]:242; CHECK-NEXT: [[OUTER_IV:%.*]] = phi i64 [ [[OUTER_IV_NEXT:%.*]], [[OUTER_LATCH:%.*]] ], [ 0, %[[ENTRY]] ]243; CHECK-NEXT: [[TMP1:%.*]] = shl i64 [[OUTER_IV]], 2244; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr nuw i8, ptr [[A]], i64 [[TMP1]]245; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[TMP1]], 4246; CHECK-NEXT: [[SCEVGEP1:%.*]] = getelementptr i8, ptr [[A]], i64 [[TMP2]]247; CHECK-NEXT: [[GEP_A:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[OUTER_IV]]248; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[N]], 4249; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], [[SCALAR_PH:label %.*]], label %[[VECTOR_MEMCHECK:.*]]250; CHECK: [[VECTOR_MEMCHECK]]:251; CHECK-NEXT: [[BOUND0:%.*]] = icmp ult ptr [[SCEVGEP]], [[SCEVGEP2]]252; CHECK-NEXT: [[BOUND1:%.*]] = icmp ult ptr [[B]], [[SCEVGEP1]]253; CHECK-NEXT: [[FOUND_CONFLICT:%.*]] = and i1 [[BOUND0]], [[BOUND1]]254; CHECK-NEXT: br i1 [[FOUND_CONFLICT]], [[SCALAR_PH]], [[VECTOR_PH:label %.*]]255;256 257 258entry:259 br label %outer.header260 261outer.header:262 %outer.iv = phi i64 [ %outer.iv.next, %outer.latch ], [ 0, %entry ]263 %gep.a = getelementptr inbounds i32, ptr %a, i64 %outer.iv264 br label %inner.body265 266inner.body:267 %inner.iv = phi i64 [ 0, %outer.header ], [ %inner.iv.next, %inner.body ]268 %gep.b = getelementptr inbounds i32, ptr %b, i64 %inner.iv269 %l = load i32, ptr %gep.b, align 4270 %sub = sub i32 %l, 10271 store i32 %sub, ptr %gep.a, align 4272 %inner.iv.next = add nuw nsw i64 %inner.iv, 1273 %inner.cond = icmp eq i64 %inner.iv.next, %n274 br i1 %inner.cond, label %outer.latch, label %inner.body275 276outer.latch:277 %outer.iv.next = add nuw nsw i64 %outer.iv, 1278 %outer.cond = icmp eq i64 %outer.iv.next, %n279 br i1 %outer.cond, label %exit, label %outer.header280 281exit:282 ret void283}284 285; Same as @nested_loop_outer_iv_addrec_invariant_in_inner1 but with dependence286; sink and source swapped.287define void @nested_loop_outer_iv_addrec_invariant_in_inner2(ptr %a, ptr %b, i64 %n) {288; CHECK-LABEL: define void @nested_loop_outer_iv_addrec_invariant_in_inner2(289; CHECK-SAME: ptr [[A:%.*]], ptr [[B:%.*]], i64 [[N:%.*]]) {290; CHECK-NEXT: [[ENTRY:.*]]:291; CHECK-NEXT: [[TMP0:%.*]] = shl i64 [[N]], 2292; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[B]], i64 [[TMP0]]293; CHECK-NEXT: br label %[[OUTER_HEADER:.*]]294; CHECK: [[OUTER_HEADER]]:295; CHECK-NEXT: [[OUTER_IV:%.*]] = phi i64 [ [[OUTER_IV_NEXT:%.*]], [[OUTER_LATCH:%.*]] ], [ 0, %[[ENTRY]] ]296; CHECK-NEXT: [[TMP1:%.*]] = shl i64 [[OUTER_IV]], 2297; CHECK-NEXT: [[SCEVGEP1:%.*]] = getelementptr nuw i8, ptr [[A]], i64 [[TMP1]]298; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[TMP1]], 4299; CHECK-NEXT: [[SCEVGEP2:%.*]] = getelementptr i8, ptr [[A]], i64 [[TMP2]]300; CHECK-NEXT: [[GEP_A:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[OUTER_IV]]301; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[N]], 4302; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], [[SCALAR_PH:label %.*]], label %[[VECTOR_MEMCHECK:.*]]303; CHECK: [[VECTOR_MEMCHECK]]:304; CHECK-NEXT: [[BOUND0:%.*]] = icmp ult ptr [[B]], [[SCEVGEP2]]305; CHECK-NEXT: [[BOUND1:%.*]] = icmp ult ptr [[SCEVGEP1]], [[SCEVGEP]]306; CHECK-NEXT: [[FOUND_CONFLICT:%.*]] = and i1 [[BOUND0]], [[BOUND1]]307; CHECK-NEXT: br i1 [[FOUND_CONFLICT]], [[SCALAR_PH]], [[VECTOR_PH:label %.*]]308;309 310 311entry:312 br label %outer.header313 314outer.header:315 %outer.iv = phi i64 [ %outer.iv.next, %outer.latch ], [ 0, %entry ]316 %gep.a = getelementptr inbounds i32, ptr %a, i64 %outer.iv317 br label %inner.body318 319inner.body:320 %inner.iv = phi i64 [ 0, %outer.header ], [ %inner.iv.next, %inner.body ]321 %l = load i32, ptr %gep.a, align 4322 %sub = sub i32 %l, 10323 %gep.b = getelementptr inbounds i32, ptr %b, i64 %inner.iv324 store i32 %sub, ptr %gep.b, align 4325 %inner.iv.next = add nuw nsw i64 %inner.iv, 1326 %inner.cond = icmp eq i64 %inner.iv.next, %n327 br i1 %inner.cond, label %outer.latch, label %inner.body328 329outer.latch:330 %outer.iv.next = add nuw nsw i64 %outer.iv, 1331 %outer.cond = icmp eq i64 %outer.iv.next, %n332 br i1 %outer.cond, label %exit, label %outer.header333 334exit:335 ret void336}337 338; Test case where the AddRec for the pointers in the inner loop have the AddRec339; of the outer loop as start value. It is sufficient to subtract the start340; values (%dst, %src) of the outer AddRecs.341define void @nested_loop_start_of_inner_ptr_addrec_is_same_outer_addrec(ptr nocapture noundef %dst, ptr nocapture noundef readonly %src, i64 noundef %m, i64 noundef %n) {342; CHECK-LABEL: define void @nested_loop_start_of_inner_ptr_addrec_is_same_outer_addrec(343; CHECK-SAME: ptr noundef captures(none) [[DST:%.*]], ptr noundef readonly captures(none) [[SRC:%.*]], i64 noundef [[M:%.*]], i64 noundef [[N:%.*]]) {344; CHECK-NEXT: [[ENTRY:.*]]:345; CHECK-NEXT: [[SRC2:%.*]] = ptrtoint ptr [[SRC]] to i64346; CHECK-NEXT: [[DST1:%.*]] = ptrtoint ptr [[DST]] to i64347; CHECK-NEXT: [[SUB:%.*]] = sub i64 [[DST1]], [[SRC2]]348; CHECK-NEXT: br label %[[OUTER_LOOP:.*]]349; CHECK: [[OUTER_LOOP]]:350; CHECK-NEXT: [[OUTER_IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[OUTER_IV_NEXT:%.*]], [[INNER_EXIT:%.*]] ]351; CHECK-NEXT: [[MUL:%.*]] = mul nsw i64 [[OUTER_IV]], [[N]]352; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[N]], 4353; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], [[SCALAR_PH:label %.*]], label %[[VECTOR_MEMCHECK:.*]]354; CHECK: [[VECTOR_MEMCHECK]]:355; CHECK-NEXT: [[DIFF_CHECK:%.*]] = icmp ult i64 [[SUB]], 16356; CHECK-NEXT: br i1 [[DIFF_CHECK]], [[SCALAR_PH]], [[VECTOR_PH:label %.*]]357;358entry:359 br label %outer.loop360 361outer.loop:362 %outer.iv = phi i64 [ 0, %entry ], [ %outer.iv.next, %inner.exit ]363 %mul = mul nsw i64 %outer.iv, %n364 br label %inner.loop365 366inner.loop:367 %iv.inner = phi i64 [ 0, %outer.loop ], [ %iv.inner.next, %inner.loop ]368 %idx = add nuw nsw i64 %iv.inner, %mul369 %gep.src = getelementptr inbounds i32, ptr %src, i64 %idx370 %l = load i32, ptr %gep.src, align 4371 %gep.dst = getelementptr inbounds i32, ptr %dst, i64 %idx372 %add = add nsw i32 %l, 10373 store i32 %add, ptr %gep.dst, align 4374 %iv.inner.next = add nuw nsw i64 %iv.inner, 1375 %inner.exit.cond = icmp eq i64 %iv.inner.next, %n376 br i1 %inner.exit.cond, label %inner.exit, label %inner.loop377 378inner.exit:379 %outer.iv.next = add nuw nsw i64 %outer.iv, 1380 %outer.exit.cond = icmp eq i64 %outer.iv.next, %m381 br i1 %outer.exit.cond, label %outer.exit, label %outer.loop382 383outer.exit:384 ret void385}386 387define void @use_diff_checks_when_retrying_with_rt_checks(i64 %off, ptr %dst, ptr %src) {388; CHECK-LABEL: define void @use_diff_checks_when_retrying_with_rt_checks(389; CHECK-SAME: i64 [[OFF:%.*]], ptr [[DST:%.*]], ptr [[SRC:%.*]]) {390; CHECK-NEXT: [[ENTRY:.*:]]391; CHECK-NEXT: [[SRC2:%.*]] = ptrtoint ptr [[SRC]] to i64392; CHECK-NEXT: [[DST1:%.*]] = ptrtoint ptr [[DST]] to i64393; CHECK-NEXT: br label %[[VECTOR_MEMCHECK:.*]]394; CHECK: [[VECTOR_MEMCHECK]]:395; CHECK-NEXT: [[TMP0:%.*]] = mul i64 [[OFF]], -8396; CHECK-NEXT: [[DIFF_CHECK:%.*]] = icmp ult i64 [[TMP0]], 32397; CHECK-NEXT: [[TMP1:%.*]] = shl i64 [[OFF]], 3398; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[DST1]], [[TMP1]]399; CHECK-NEXT: [[TMP3:%.*]] = sub i64 [[TMP2]], [[SRC2]]400; CHECK-NEXT: [[DIFF_CHECK3:%.*]] = icmp ult i64 [[TMP3]], 32401; CHECK-NEXT: [[CONFLICT_RDX:%.*]] = or i1 [[DIFF_CHECK]], [[DIFF_CHECK3]]402; CHECK-NEXT: [[TMP4:%.*]] = add i64 [[SRC2]], 8403; CHECK-NEXT: [[TMP5:%.*]] = sub i64 [[TMP4]], [[DST1]]404; CHECK-NEXT: [[TMP6:%.*]] = sub i64 [[TMP5]], [[TMP1]]405; CHECK-NEXT: [[DIFF_CHECK4:%.*]] = icmp ult i64 [[TMP6]], 32406; CHECK-NEXT: [[CONFLICT_RDX5:%.*]] = or i1 [[CONFLICT_RDX]], [[DIFF_CHECK4]]407; CHECK-NEXT: [[TMP7:%.*]] = sub i64 [[DST1]], [[SRC2]]408; CHECK-NEXT: [[DIFF_CHECK6:%.*]] = icmp ult i64 [[TMP7]], 32409; CHECK-NEXT: [[CONFLICT_RDX7:%.*]] = or i1 [[CONFLICT_RDX5]], [[DIFF_CHECK6]]410; CHECK-NEXT: [[TMP8:%.*]] = add i64 [[DST1]], -8411; CHECK-NEXT: [[TMP9:%.*]] = sub i64 [[TMP8]], [[SRC2]]412; CHECK-NEXT: [[DIFF_CHECK8:%.*]] = icmp ult i64 [[TMP9]], 32413; CHECK-NEXT: [[CONFLICT_RDX9:%.*]] = or i1 [[CONFLICT_RDX7]], [[DIFF_CHECK8]]414; CHECK-NEXT: br i1 [[CONFLICT_RDX9]], [[SCALAR_PH:label %.*]], [[VECTOR_PH:label %.*]]415;416entry:417 br label %loop418 419loop:420 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]421 %iv.off = add i64 %off, %iv422 %gep.src = getelementptr i64, ptr %src, i64 %iv423 %l.0 = load i64, ptr %gep.src, align 8424 %gep.dst.off = getelementptr i64, ptr %dst, i64 %iv.off425 store i64 %l.0, ptr %gep.dst.off, align 8426 %gep.src.8 = getelementptr i8, ptr %gep.src, i64 8427 %l.1 = load i64, ptr %gep.src.8, align 8428 %gep.dst.iv = getelementptr i64, ptr %dst, i64 %iv429 store i64 %l.1, ptr %gep.dst.iv, align 8430 %iv.next = add i64 %iv, 1431 %ec = icmp eq i64 %iv.next, 1000432 br i1 %ec, label %exit, label %loop433 434exit:435 ret void436}437 438 439define void @remove_diff_checks_via_guards(i32 %x, i32 %y, ptr %A) {440; CHECK-LABEL: define void @remove_diff_checks_via_guards(441; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]], ptr [[A:%.*]]) {442; CHECK-NEXT: [[ENTRY:.*:]]443; CHECK-NEXT: [[OFFSET:%.*]] = sub i32 [[X]], [[Y]]444; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[OFFSET]], 0445; CHECK-NEXT: br i1 [[CMP]], [[EXIT:label %.*]], label %[[LOOP_PREHEADER:.*]]446; CHECK: [[LOOP_PREHEADER]]:447; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[X]] to i64448; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[TMP0]], 1449; CHECK-NEXT: [[SMAX2:%.*]] = call i64 @llvm.smax.i64(i64 [[TMP1]], i64 0)450; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[SMAX2]] to i32451; CHECK-NEXT: [[TMP3:%.*]] = add nuw i32 [[TMP2]], 1452; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[TMP3]], 4453; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], [[SCALAR_PH:label %.*]], label %[[VECTOR_SCEVCHECK:.*]]454; CHECK: [[VECTOR_SCEVCHECK]]:455; CHECK-NEXT: [[TMP4:%.*]] = sext i32 [[X]] to i64456; CHECK-NEXT: [[TMP5:%.*]] = add nsw i64 [[TMP4]], 1457; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[TMP5]], i64 0)458; CHECK-NEXT: [[TMP6:%.*]] = trunc i64 [[SMAX]] to i32459; CHECK-NEXT: [[TMP7:%.*]] = icmp slt i32 [[TMP6]], 0460; CHECK-NEXT: [[TMP8:%.*]] = icmp ugt i64 [[SMAX]], 4294967295461; CHECK-NEXT: [[TMP9:%.*]] = or i1 [[TMP7]], [[TMP8]]462; CHECK-NEXT: [[TMP10:%.*]] = trunc i64 [[SMAX]] to i32463; CHECK-NEXT: [[TMP11:%.*]] = add i32 [[OFFSET]], [[TMP10]]464; CHECK-NEXT: [[TMP12:%.*]] = icmp slt i32 [[TMP11]], [[OFFSET]]465; CHECK-NEXT: [[TMP13:%.*]] = icmp ugt i64 [[SMAX]], 4294967295466; CHECK-NEXT: [[TMP14:%.*]] = or i1 [[TMP12]], [[TMP13]]467; CHECK-NEXT: [[TMP15:%.*]] = or i1 [[TMP9]], [[TMP14]]468; CHECK-NEXT: br i1 [[TMP15]], [[SCALAR_PH]], label %[[VECTOR_MEMCHECK:.*]]469; CHECK: [[VECTOR_MEMCHECK]]:470; CHECK-NEXT: [[TMP16:%.*]] = sext i32 [[OFFSET]] to i64471; CHECK-NEXT: [[TMP17:%.*]] = shl nsw i64 [[TMP16]], 2472; CHECK-NEXT: [[DIFF_CHECK:%.*]] = icmp ult i64 [[TMP17]], 16473; CHECK-NEXT: br i1 [[DIFF_CHECK]], [[SCALAR_PH]], [[VECTOR_PH1:label %.*]]474;475entry:476 %offset = sub i32 %x, %y477 %cmp = icmp sge i32 %offset, 0478 br i1 %cmp, label %exit, label %loop479 480loop:481 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]482 %iv.ext = sext i32 %iv to i64483 %gep.A = getelementptr i32, ptr %A, i64 %iv.ext484 %l = load i32, ptr %gep.A, align 1485 %iv.offset = add i32 %iv, %offset486 %iv.offset.ext = sext i32 %iv.offset to i64487 %gep.A.offset = getelementptr i32, ptr %A, i64 %iv.offset.ext488 store i32 %l, ptr %gep.A.offset, align 1489 %iv.next = add i32 %iv, 1490 %ec = icmp sgt i32 %iv, %x491 br i1 %ec, label %exit, label %loop492 493exit:494 ret void495}496