1056 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals none --version 62; RUN: opt -S < %s -p loop-vectorize -enable-early-exit-vectorization -force-vector-width=4 | FileCheck %s3 4define i64 @early_exit_alignment_and_deref_known_via_assumption_with_constant_size(ptr noalias %p1, ptr noalias %p2) nofree nosync {5; CHECK-LABEL: define i64 @early_exit_alignment_and_deref_known_via_assumption_with_constant_size(6; CHECK-SAME: ptr noalias [[P1:%.*]], ptr noalias [[P2:%.*]]) #[[ATTR0:[0-9]+]] {7; CHECK-NEXT: [[ENTRY:.*:]]8; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[P1]], i64 4), "dereferenceable"(ptr [[P1]], i64 1024) ]9; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[P2]], i64 4), "dereferenceable"(ptr [[P2]], i64 1024) ]10; CHECK-NEXT: br label %[[VECTOR_PH:.*]]11; CHECK: [[VECTOR_PH]]:12; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]13; CHECK: [[VECTOR_BODY]]:14; CHECK-NEXT: [[INDEX1:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT3:%.*]], %[[VECTOR_BODY]] ]15; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[INDEX1]]16; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i8>, ptr [[TMP0]], align 117; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 [[INDEX1]]18; CHECK-NEXT: [[WIDE_LOAD2:%.*]] = load <4 x i8>, ptr [[TMP2]], align 119; CHECK-NEXT: [[TMP4:%.*]] = icmp ne <4 x i8> [[WIDE_LOAD]], [[WIDE_LOAD2]]20; CHECK-NEXT: [[INDEX_NEXT3]] = add nuw i64 [[INDEX1]], 421; CHECK-NEXT: [[TMP3:%.*]] = freeze <4 x i1> [[TMP4]]22; CHECK-NEXT: [[TMP5:%.*]] = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> [[TMP3]])23; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[INDEX_NEXT3]], 102424; CHECK-NEXT: [[TMP7:%.*]] = or i1 [[TMP5]], [[TMP6]]25; CHECK-NEXT: br i1 [[TMP7]], label %[[MIDDLE_SPLIT:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]]26; CHECK: [[MIDDLE_SPLIT]]:27; CHECK-NEXT: br i1 [[TMP5]], label %[[VECTOR_EARLY_EXIT:.*]], label %[[MIDDLE_BLOCK:.*]]28; CHECK: [[MIDDLE_BLOCK]]:29; CHECK-NEXT: br label %[[LOOP_END:.*]]30; CHECK: [[VECTOR_EARLY_EXIT]]:31; CHECK-NEXT: [[TMP8:%.*]] = call i64 @llvm.experimental.cttz.elts.i64.v4i1(<4 x i1> [[TMP4]], i1 false)32; CHECK-NEXT: [[TMP9:%.*]] = add i64 [[INDEX1]], [[TMP8]]33; CHECK-NEXT: br label %[[LOOP_END]]34; CHECK: [[LOOP_END]]:35; CHECK-NEXT: [[RETVAL:%.*]] = phi i64 [ -1, %[[MIDDLE_BLOCK]] ], [ [[TMP9]], %[[VECTOR_EARLY_EXIT]] ]36; CHECK-NEXT: ret i64 [[RETVAL]]37;38entry:39 call void @llvm.assume(i1 true) [ "align"(ptr %p1, i64 4), "dereferenceable"(ptr %p1, i64 1024) ]40 call void @llvm.assume(i1 true) [ "align"(ptr %p2, i64 4), "dereferenceable"(ptr %p2, i64 1024) ]41 br label %loop42 43loop:44 %index = phi i64 [ %index.next, %loop.inc ], [ 0, %entry ]45 %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index46 %ld1 = load i8, ptr %arrayidx, align 147 %arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index48 %ld2 = load i8, ptr %arrayidx1, align 149 %cmp3 = icmp eq i8 %ld1, %ld250 br i1 %cmp3, label %loop.inc, label %loop.end51 52loop.inc:53 %index.next = add i64 %index, 154 %exitcond = icmp ne i64 %index.next, 102455 br i1 %exitcond, label %loop, label %loop.end56 57loop.end:58 %retval = phi i64 [ %index, %loop ], [ -1, %loop.inc ]59 ret i64 %retval60}61 62define i64 @early_exit_alignment_and_deref_via_assumption_with_constant_size_too_small(ptr noalias %p1, ptr noalias %p2) nofree nosync {63; CHECK-LABEL: define i64 @early_exit_alignment_and_deref_via_assumption_with_constant_size_too_small(64; CHECK-SAME: ptr noalias [[P1:%.*]], ptr noalias [[P2:%.*]]) #[[ATTR0]] {65; CHECK-NEXT: [[ENTRY:.*]]:66; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[P1]], i64 4), "dereferenceable"(ptr [[P1]], i64 1024) ]67; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[P2]], i64 4), "dereferenceable"(ptr [[P2]], i64 1024) ]68; CHECK-NEXT: br label %[[LOOP:.*]]69; CHECK: [[LOOP]]:70; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], %[[LOOP_INC:.*]] ], [ 0, %[[ENTRY]] ]71; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[INDEX]]72; CHECK-NEXT: [[LD1:%.*]] = load i8, ptr [[ARRAYIDX]], align 173; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 [[INDEX]]74; CHECK-NEXT: [[LD2:%.*]] = load i8, ptr [[ARRAYIDX1]], align 175; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i8 [[LD1]], [[LD2]]76; CHECK-NEXT: br i1 [[CMP3]], label %[[LOOP_INC]], label %[[LOOP_END:.*]]77; CHECK: [[LOOP_INC]]:78; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 179; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], 102580; CHECK-NEXT: br i1 [[EXITCOND]], label %[[LOOP]], label %[[LOOP_END]]81; CHECK: [[LOOP_END]]:82; CHECK-NEXT: [[RETVAL:%.*]] = phi i64 [ [[INDEX]], %[[LOOP]] ], [ -1, %[[LOOP_INC]] ]83; CHECK-NEXT: ret i64 [[RETVAL]]84;85entry:86 call void @llvm.assume(i1 true) [ "align"(ptr %p1, i64 4), "dereferenceable"(ptr %p1, i64 1024) ]87 call void @llvm.assume(i1 true) [ "align"(ptr %p2, i64 4), "dereferenceable"(ptr %p2, i64 1024) ]88 br label %loop89 90loop:91 %index = phi i64 [ %index.next, %loop.inc ], [ 0, %entry ]92 %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index93 %ld1 = load i8, ptr %arrayidx, align 194 %arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index95 %ld2 = load i8, ptr %arrayidx1, align 196 %cmp3 = icmp eq i8 %ld1, %ld297 br i1 %cmp3, label %loop.inc, label %loop.end98 99loop.inc:100 %index.next = add i64 %index, 1101 %exitcond = icmp ne i64 %index.next, 1025102 br i1 %exitcond, label %loop, label %loop.end103 104loop.end:105 %retval = phi i64 [ %index, %loop ], [ -1, %loop.inc ]106 ret i64 %retval107}108 109define i64 @early_exit_alignment_and_deref_known_via_assumption_n_not_zero(ptr noalias %p1, ptr noalias %p2, i64 %n) nofree nosync {110; CHECK-LABEL: define i64 @early_exit_alignment_and_deref_known_via_assumption_n_not_zero(111; CHECK-SAME: ptr noalias [[P1:%.*]], ptr noalias [[P2:%.*]], i64 [[N:%.*]]) #[[ATTR0]] {112; CHECK-NEXT: [[ENTRY:.*]]:113; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[P1]], i64 4), "dereferenceable"(ptr [[P1]], i64 [[N]]) ]114; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[P2]], i64 4), "dereferenceable"(ptr [[P2]], i64 [[N]]) ]115; CHECK-NEXT: [[C:%.*]] = icmp ne i64 [[N]], 0116; CHECK-NEXT: br i1 [[C]], label %[[LOOP_PREHEADER:.*]], label %[[LOOP_END:.*]]117; CHECK: [[LOOP_PREHEADER]]:118; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[N]], 4119; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]120; CHECK: [[VECTOR_PH]]:121; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[N]], 4122; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[N]], [[N_MOD_VF]]123; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]124; CHECK: [[VECTOR_BODY]]:125; CHECK-NEXT: [[INDEX1:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT3:%.*]], %[[VECTOR_BODY]] ]126; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[INDEX1]]127; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i8>, ptr [[TMP0]], align 1128; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 [[INDEX1]]129; CHECK-NEXT: [[WIDE_LOAD2:%.*]] = load <4 x i8>, ptr [[TMP1]], align 1130; CHECK-NEXT: [[TMP2:%.*]] = icmp ne <4 x i8> [[WIDE_LOAD]], [[WIDE_LOAD2]]131; CHECK-NEXT: [[INDEX_NEXT3]] = add nuw i64 [[INDEX1]], 4132; CHECK-NEXT: [[TMP3:%.*]] = freeze <4 x i1> [[TMP2]]133; CHECK-NEXT: [[TMP4:%.*]] = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> [[TMP3]])134; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i64 [[INDEX_NEXT3]], [[N_VEC]]135; CHECK-NEXT: [[TMP6:%.*]] = or i1 [[TMP4]], [[TMP5]]136; CHECK-NEXT: br i1 [[TMP6]], label %[[MIDDLE_SPLIT:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP3:![0-9]+]]137; CHECK: [[MIDDLE_SPLIT]]:138; CHECK-NEXT: br i1 [[TMP4]], label %[[VECTOR_EARLY_EXIT:.*]], label %[[MIDDLE_BLOCK:.*]]139; CHECK: [[MIDDLE_BLOCK]]:140; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[N]], [[N_VEC]]141; CHECK-NEXT: br i1 [[CMP_N]], label %[[LOOP_END_LOOPEXIT:.*]], label %[[SCALAR_PH]]142; CHECK: [[VECTOR_EARLY_EXIT]]:143; CHECK-NEXT: [[TMP7:%.*]] = call i64 @llvm.experimental.cttz.elts.i64.v4i1(<4 x i1> [[TMP2]], i1 false)144; CHECK-NEXT: [[TMP8:%.*]] = add i64 [[INDEX1]], [[TMP7]]145; CHECK-NEXT: br label %[[LOOP_END_LOOPEXIT]]146; CHECK: [[SCALAR_PH]]:147; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], %[[MIDDLE_BLOCK]] ], [ 0, %[[LOOP_PREHEADER]] ]148; CHECK-NEXT: br label %[[LOOP:.*]]149; CHECK: [[LOOP]]:150; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], %[[LOOP_INC:.*]] ], [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ]151; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[INDEX]]152; CHECK-NEXT: [[LD1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1153; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 [[INDEX]]154; CHECK-NEXT: [[LD2:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1155; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i8 [[LD1]], [[LD2]]156; CHECK-NEXT: br i1 [[CMP3]], label %[[LOOP_INC]], label %[[LOOP_END_LOOPEXIT]]157; CHECK: [[LOOP_INC]]:158; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 1159; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], [[N]]160; CHECK-NEXT: br i1 [[EXITCOND]], label %[[LOOP]], label %[[LOOP_END_LOOPEXIT]], !llvm.loop [[LOOP4:![0-9]+]]161; CHECK: [[LOOP_END_LOOPEXIT]]:162; CHECK-NEXT: [[RETVAL_PH:%.*]] = phi i64 [ -1, %[[LOOP_INC]] ], [ [[INDEX]], %[[LOOP]] ], [ -1, %[[MIDDLE_BLOCK]] ], [ [[TMP8]], %[[VECTOR_EARLY_EXIT]] ]163; CHECK-NEXT: br label %[[LOOP_END]]164; CHECK: [[LOOP_END]]:165; CHECK-NEXT: [[RETVAL:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[RETVAL_PH]], %[[LOOP_END_LOOPEXIT]] ]166; CHECK-NEXT: ret i64 [[RETVAL]]167;168entry:169 call void @llvm.assume(i1 true) [ "align"(ptr %p1, i64 4), "dereferenceable"(ptr %p1, i64 %n) ]170 call void @llvm.assume(i1 true) [ "align"(ptr %p2, i64 4), "dereferenceable"(ptr %p2, i64 %n) ]171 %c = icmp ne i64 %n, 0172 br i1 %c, label %loop, label %loop.end173 174loop:175 %index = phi i64 [ %index.next, %loop.inc ], [ 0, %entry ]176 %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index177 %ld1 = load i8, ptr %arrayidx, align 1178 %arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index179 %ld2 = load i8, ptr %arrayidx1, align 1180 %cmp3 = icmp eq i8 %ld1, %ld2181 br i1 %cmp3, label %loop.inc, label %loop.end182 183loop.inc:184 %index.next = add i64 %index, 1185 %exitcond = icmp ne i64 %index.next, %n186 br i1 %exitcond, label %loop, label %loop.end187 188loop.end:189 %retval = phi i64 [ 0, %entry ], [ %index, %loop ], [ -1, %loop.inc ]190 ret i64 %retval191}192 193define i64 @early_exit_alignment_and_deref_known_via_assumption_n_may_be_zero(ptr noalias %p1, ptr noalias %p2, i64 %n) nofree nosync {194; CHECK-LABEL: define i64 @early_exit_alignment_and_deref_known_via_assumption_n_may_be_zero(195; CHECK-SAME: ptr noalias [[P1:%.*]], ptr noalias [[P2:%.*]], i64 [[N:%.*]]) #[[ATTR0]] {196; CHECK-NEXT: [[ENTRY:.*]]:197; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[P1]], i64 4), "dereferenceable"(ptr [[P1]], i64 [[N]]) ]198; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[P2]], i64 4), "dereferenceable"(ptr [[P2]], i64 [[N]]) ]199; CHECK-NEXT: br label %[[LOOP:.*]]200; CHECK: [[LOOP]]:201; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], %[[LOOP_INC:.*]] ], [ 0, %[[ENTRY]] ]202; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[INDEX]]203; CHECK-NEXT: [[LD1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1204; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 [[INDEX]]205; CHECK-NEXT: [[LD2:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1206; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i8 [[LD1]], [[LD2]]207; CHECK-NEXT: br i1 [[CMP3]], label %[[LOOP_INC]], label %[[LOOP_END:.*]]208; CHECK: [[LOOP_INC]]:209; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 1210; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], [[N]]211; CHECK-NEXT: br i1 [[EXITCOND]], label %[[LOOP]], label %[[LOOP_END]]212; CHECK: [[LOOP_END]]:213; CHECK-NEXT: [[RETVAL:%.*]] = phi i64 [ [[INDEX]], %[[LOOP]] ], [ -1, %[[LOOP_INC]] ]214; CHECK-NEXT: ret i64 [[RETVAL]]215;216entry:217 call void @llvm.assume(i1 true) [ "align"(ptr %p1, i64 4), "dereferenceable"(ptr %p1, i64 %n) ]218 call void @llvm.assume(i1 true) [ "align"(ptr %p2, i64 4), "dereferenceable"(ptr %p2, i64 %n) ]219 br label %loop220 221loop:222 %index = phi i64 [ %index.next, %loop.inc ], [ 0, %entry ]223 %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index224 %ld1 = load i8, ptr %arrayidx, align 1225 %arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index226 %ld2 = load i8, ptr %arrayidx1, align 1227 %cmp3 = icmp eq i8 %ld1, %ld2228 br i1 %cmp3, label %loop.inc, label %loop.end229 230loop.inc:231 %index.next = add i64 %index, 1232 %exitcond = icmp ne i64 %index.next, %n233 br i1 %exitcond, label %loop, label %loop.end234 235loop.end:236 %retval = phi i64 [ %index, %loop ], [ -1, %loop.inc ]237 ret i64 %retval238}239 240define i64 @early_exit_alignment_and_deref_known_via_assumption_n_not_zero_i16(ptr noalias %p1, ptr noalias %p2, i32 %n) nofree nosync {241; CHECK-LABEL: define i64 @early_exit_alignment_and_deref_known_via_assumption_n_not_zero_i16(242; CHECK-SAME: ptr noalias [[P1:%.*]], ptr noalias [[P2:%.*]], i32 [[N:%.*]]) #[[ATTR0]] {243; CHECK-NEXT: [[ENTRY:.*]]:244; CHECK-NEXT: [[N_EXT:%.*]] = zext i32 [[N]] to i64245; CHECK-NEXT: [[N_SCALED:%.*]] = shl nuw nsw i64 [[N_EXT]], 1246; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[P1]], i64 4), "dereferenceable"(ptr [[P1]], i64 [[N_SCALED]]) ]247; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[P2]], i64 4), "dereferenceable"(ptr [[P2]], i64 [[N_SCALED]]) ]248; CHECK-NEXT: [[C:%.*]] = icmp ne i64 [[N_EXT]], 0249; CHECK-NEXT: br i1 [[C]], label %[[LOOP_PREHEADER:.*]], label %[[LOOP_END:.*]]250; CHECK: [[LOOP_PREHEADER]]:251; CHECK-NEXT: br label %[[LOOP:.*]]252; CHECK: [[LOOP]]:253; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], %[[LOOP_INC:.*]] ], [ 0, %[[LOOP_PREHEADER]] ]254; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[INDEX]]255; CHECK-NEXT: [[LD1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1256; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 [[INDEX]]257; CHECK-NEXT: [[LD2:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1258; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i8 [[LD1]], [[LD2]]259; CHECK-NEXT: br i1 [[CMP3]], label %[[LOOP_INC]], label %[[LOOP_END_LOOPEXIT:.*]]260; CHECK: [[LOOP_INC]]:261; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 1262; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], [[N_EXT]]263; CHECK-NEXT: br i1 [[EXITCOND]], label %[[LOOP]], label %[[LOOP_END_LOOPEXIT]]264; CHECK: [[LOOP_END_LOOPEXIT]]:265; CHECK-NEXT: [[RETVAL_PH:%.*]] = phi i64 [ -1, %[[LOOP_INC]] ], [ [[INDEX]], %[[LOOP]] ]266; CHECK-NEXT: br label %[[LOOP_END]]267; CHECK: [[LOOP_END]]:268; CHECK-NEXT: [[RETVAL:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[RETVAL_PH]], %[[LOOP_END_LOOPEXIT]] ]269; CHECK-NEXT: ret i64 [[RETVAL]]270;271entry:272 %n.ext = zext i32 %n to i64273 %n.scaled = shl nuw nsw i64 %n.ext, 1274 call void @llvm.assume(i1 true) [ "align"(ptr %p1, i64 4), "dereferenceable"(ptr %p1, i64 %n.scaled) ]275 call void @llvm.assume(i1 true) [ "align"(ptr %p2, i64 4), "dereferenceable"(ptr %p2, i64 %n.scaled) ]276 %c = icmp ne i64 %n.ext, 0277 br i1 %c, label %loop, label %loop.end278 279loop:280 %index = phi i64 [ 0, %entry ], [ %index.next, %loop.inc ]281 %gep.p1 = getelementptr inbounds i8, ptr %p1, i64 %index282 %ld1 = load i8, ptr %gep.p1, align 1283 %gep.p2 = getelementptr inbounds i8, ptr %p2, i64 %index284 %ld2 = load i8, ptr %gep.p2, align 1285 %c.0 = icmp eq i8 %ld1, %ld2286 br i1 %c.0, label %loop.inc, label %loop.end287 288loop.inc:289 %index.next = add i64 %index, 1290 %exitcond = icmp ne i64 %index.next, %n.ext291 br i1 %exitcond, label %loop, label %loop.end292 293loop.end:294 %retval = phi i64 [ 0, %entry ], [ %index, %loop ], [ -1, %loop.inc ]295 ret i64 %retval296}297 298define i64 @early_exit_alignment_and_deref_known_via_assumption_n_not_zero_i16_ptr_iv(ptr %A, i32 noundef %n) nofree nosync {299; CHECK-LABEL: define i64 @early_exit_alignment_and_deref_known_via_assumption_n_not_zero_i16_ptr_iv(300; CHECK-SAME: ptr [[A:%.*]], i32 noundef [[N:%.*]]) #[[ATTR0]] {301; CHECK-NEXT: [[ENTRY:.*]]:302; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[A]], i64 2) ]303; CHECK-NEXT: [[N_EXT:%.*]] = zext i32 [[N]] to i64304; CHECK-NEXT: [[MUL:%.*]] = shl i64 [[N_EXT]], 1305; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[A]], i64 [[MUL]]) ]306; CHECK-NEXT: [[A_END:%.*]] = getelementptr i8, ptr [[A]], i64 [[MUL]]307; CHECK-NEXT: [[PRE:%.*]] = icmp eq i32 [[N]], 0308; CHECK-NEXT: br i1 [[PRE]], label %[[EXIT:.*]], label %[[LOOP_HEADER_PREHEADER:.*]]309; CHECK: [[LOOP_HEADER_PREHEADER]]:310; CHECK-NEXT: [[TMP0:%.*]] = add nsw i64 [[MUL]], -2311; CHECK-NEXT: [[TMP1:%.*]] = lshr i64 [[TMP0]], 1312; CHECK-NEXT: [[TMP2:%.*]] = add nuw i64 [[TMP1]], 1313; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP2]], 4314; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]315; CHECK: [[VECTOR_PH]]:316; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[TMP2]], 4317; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP2]], [[N_MOD_VF]]318; CHECK-NEXT: [[TMP3:%.*]] = mul i64 [[N_VEC]], 2319; CHECK-NEXT: [[IV_NEXT1:%.*]] = getelementptr i8, ptr [[A]], i64 [[TMP3]]320; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]321; CHECK: [[VECTOR_BODY]]:322; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]323; CHECK-NEXT: [[OFFSET_IDX:%.*]] = mul i64 [[INDEX]], 2324; CHECK-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr [[A]], i64 [[OFFSET_IDX]]325; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i16>, ptr [[NEXT_GEP]], align 2326; CHECK-NEXT: [[TMP5:%.*]] = icmp eq <4 x i16> [[WIDE_LOAD]], zeroinitializer327; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4328; CHECK-NEXT: [[TMP6:%.*]] = freeze <4 x i1> [[TMP5]]329; CHECK-NEXT: [[TMP7:%.*]] = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> [[TMP6]])330; CHECK-NEXT: [[TMP8:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]331; CHECK-NEXT: [[TMP9:%.*]] = or i1 [[TMP7]], [[TMP8]]332; CHECK-NEXT: br i1 [[TMP9]], label %[[MIDDLE_SPLIT:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP5:![0-9]+]]333; CHECK: [[MIDDLE_SPLIT]]:334; CHECK-NEXT: br i1 [[TMP7]], label %[[VECTOR_EARLY_EXIT:.*]], label %[[MIDDLE_BLOCK:.*]]335; CHECK: [[MIDDLE_BLOCK]]:336; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP2]], [[N_VEC]]337; CHECK-NEXT: br i1 [[CMP_N]], label %[[EXIT_LOOPEXIT:.*]], label %[[SCALAR_PH]]338; CHECK: [[VECTOR_EARLY_EXIT]]:339; CHECK-NEXT: [[TMP10:%.*]] = call i64 @llvm.experimental.cttz.elts.i64.v4i1(<4 x i1> [[TMP5]], i1 false)340; CHECK-NEXT: [[TMP11:%.*]] = add i64 [[INDEX]], [[TMP10]]341; CHECK-NEXT: [[TMP12:%.*]] = mul i64 [[TMP11]], 2342; CHECK-NEXT: [[TMP13:%.*]] = getelementptr i8, ptr [[A]], i64 [[TMP12]]343; CHECK-NEXT: br label %[[EXIT_LOOPEXIT]]344; CHECK: [[SCALAR_PH]]:345; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi ptr [ [[IV_NEXT1]], %[[MIDDLE_BLOCK]] ], [ [[A]], %[[LOOP_HEADER_PREHEADER]] ]346; CHECK-NEXT: br label %[[LOOP_HEADER:.*]]347; CHECK: [[LOOP_HEADER]]:348; CHECK-NEXT: [[IV:%.*]] = phi ptr [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ], [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ]349; CHECK-NEXT: [[L:%.*]] = load i16, ptr [[IV]], align 2350; CHECK-NEXT: [[C_0:%.*]] = icmp eq i16 [[L]], 0351; CHECK-NEXT: br i1 [[C_0]], label %[[EXIT_LOOPEXIT]], label %[[LOOP_LATCH]]352; CHECK: [[LOOP_LATCH]]:353; CHECK-NEXT: [[IV_NEXT]] = getelementptr inbounds nuw i8, ptr [[IV]], i64 2354; CHECK-NEXT: [[EC:%.*]] = icmp eq ptr [[IV_NEXT]], [[A_END]]355; CHECK-NEXT: br i1 [[EC]], label %[[EXIT_LOOPEXIT]], label %[[LOOP_HEADER]], !llvm.loop [[LOOP6:![0-9]+]]356; CHECK: [[EXIT_LOOPEXIT]]:357; CHECK-NEXT: [[P_PH:%.*]] = phi ptr [ [[A_END]], %[[LOOP_LATCH]] ], [ [[IV]], %[[LOOP_HEADER]] ], [ [[A_END]], %[[MIDDLE_BLOCK]] ], [ [[TMP13]], %[[VECTOR_EARLY_EXIT]] ]358; CHECK-NEXT: br label %[[EXIT]]359; CHECK: [[EXIT]]:360; CHECK-NEXT: [[P:%.*]] = phi ptr [ [[A]], %[[ENTRY]] ], [ [[P_PH]], %[[EXIT_LOOPEXIT]] ]361; CHECK-NEXT: [[RES:%.*]] = ptrtoint ptr [[P]] to i64362; CHECK-NEXT: ret i64 [[RES]]363;364entry:365 call void @llvm.assume(i1 true) [ "align"(ptr %A, i64 2) ]366 %n.ext = zext i32 %n to i64367 %mul = shl nuw nsw i64 %n.ext, 1368 call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %A, i64 %mul) ]369 %A.end = getelementptr i8, ptr %A, i64 %mul370 %pre = icmp eq i32 %n, 0371 br i1 %pre, label %exit, label %loop.header372 373loop.header:374 %iv = phi ptr [ %iv.next, %loop.latch ], [ %A, %entry ]375 %l = load i16, ptr %iv, align 2376 %c.0 = icmp eq i16 %l, 0377 br i1 %c.0, label %exit, label %loop.latch378 379loop.latch:380 %iv.next = getelementptr inbounds nuw i8, ptr %iv, i64 2381 %ec = icmp eq ptr %iv.next, %A.end382 br i1 %ec, label %exit, label %loop.header383 384exit:385 %p = phi ptr [ %A, %entry ], [ %iv, %loop.header ], [ %A.end, %loop.latch ]386 %res = ptrtoint ptr %p to i64387 ret i64 %res388}389 390; The existing assumptions is strong enough to vectorize this.391define ptr @find_deref_pointer_distance_align_attribute_argument(ptr align 2 %first, ptr align 2 %last) nofree nosync {392; CHECK-LABEL: define ptr @find_deref_pointer_distance_align_attribute_argument(393; CHECK-SAME: ptr align 2 [[FIRST:%.*]], ptr align 2 [[LAST:%.*]]) #[[ATTR0]] {394; CHECK-NEXT: [[ENTRY:.*]]:395; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[FIRST]], i64 2) ]396; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[LAST]], i64 2) ]397; CHECK-NEXT: [[LAST_I64:%.*]] = ptrtoint ptr [[LAST]] to i64398; CHECK-NEXT: [[FIRST_I64:%.*]] = ptrtoint ptr [[FIRST]] to i64399; CHECK-NEXT: [[DISTANCE:%.*]] = sub i64 [[LAST_I64]], [[FIRST_I64]]400; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[FIRST]], i64 [[DISTANCE]]) ]401; CHECK-NEXT: [[C_0:%.*]] = icmp eq ptr [[FIRST]], [[LAST]]402; CHECK-NEXT: br i1 [[C_0]], label %[[EXIT:.*]], label %[[LOOP_HEADER_PREHEADER:.*]]403; CHECK: [[LOOP_HEADER_PREHEADER]]:404; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[LAST_I64]], -2405; CHECK-NEXT: [[TMP1:%.*]] = sub i64 [[TMP0]], [[FIRST_I64]]406; CHECK-NEXT: [[TMP2:%.*]] = lshr i64 [[TMP1]], 1407; CHECK-NEXT: [[TMP3:%.*]] = add nuw i64 [[TMP2]], 1408; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP3]], 4409; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]410; CHECK: [[VECTOR_PH]]:411; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[TMP3]], 4412; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP3]], [[N_MOD_VF]]413; CHECK-NEXT: [[TMP4:%.*]] = mul i64 [[N_VEC]], 2414; CHECK-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[FIRST]], i64 [[TMP4]]415; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]416; CHECK: [[VECTOR_BODY]]:417; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]418; CHECK-NEXT: [[OFFSET_IDX:%.*]] = mul i64 [[INDEX]], 2419; CHECK-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr [[FIRST]], i64 [[OFFSET_IDX]]420; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i16>, ptr [[NEXT_GEP]], align 2421; CHECK-NEXT: [[TMP6:%.*]] = icmp eq <4 x i16> [[WIDE_LOAD]], splat (i16 1)422; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4423; CHECK-NEXT: [[TMP7:%.*]] = freeze <4 x i1> [[TMP6]]424; CHECK-NEXT: [[TMP8:%.*]] = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> [[TMP7]])425; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]426; CHECK-NEXT: [[TMP10:%.*]] = or i1 [[TMP8]], [[TMP9]]427; CHECK-NEXT: br i1 [[TMP10]], label %[[MIDDLE_SPLIT:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP7:![0-9]+]]428; CHECK: [[MIDDLE_SPLIT]]:429; CHECK-NEXT: br i1 [[TMP8]], label %[[VECTOR_EARLY_EXIT:.*]], label %[[MIDDLE_BLOCK:.*]]430; CHECK: [[MIDDLE_BLOCK]]:431; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP3]], [[N_VEC]]432; CHECK-NEXT: br i1 [[CMP_N]], label %[[EXIT_LOOPEXIT:.*]], label %[[SCALAR_PH]]433; CHECK: [[VECTOR_EARLY_EXIT]]:434; CHECK-NEXT: [[TMP11:%.*]] = call i64 @llvm.experimental.cttz.elts.i64.v4i1(<4 x i1> [[TMP6]], i1 false)435; CHECK-NEXT: [[TMP12:%.*]] = add i64 [[INDEX]], [[TMP11]]436; CHECK-NEXT: [[TMP13:%.*]] = mul i64 [[TMP12]], 2437; CHECK-NEXT: [[TMP14:%.*]] = getelementptr i8, ptr [[FIRST]], i64 [[TMP13]]438; CHECK-NEXT: br label %[[EXIT_LOOPEXIT]]439; CHECK: [[SCALAR_PH]]:440; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi ptr [ [[TMP5]], %[[MIDDLE_BLOCK]] ], [ [[FIRST]], %[[LOOP_HEADER_PREHEADER]] ]441; CHECK-NEXT: br label %[[LOOP_HEADER:.*]]442; CHECK: [[LOOP_HEADER]]:443; CHECK-NEXT: [[IV:%.*]] = phi ptr [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ], [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ]444; CHECK-NEXT: [[L:%.*]] = load i16, ptr [[IV]], align 2445; CHECK-NEXT: [[C_1:%.*]] = icmp eq i16 [[L]], 1446; CHECK-NEXT: br i1 [[C_1]], label %[[EXIT_LOOPEXIT]], label %[[LOOP_LATCH]]447; CHECK: [[LOOP_LATCH]]:448; CHECK-NEXT: [[IV_NEXT]] = getelementptr inbounds nuw i8, ptr [[IV]], i64 2449; CHECK-NEXT: [[C_2:%.*]] = icmp eq ptr [[IV_NEXT]], [[LAST]]450; CHECK-NEXT: br i1 [[C_2]], label %[[EXIT_LOOPEXIT]], label %[[LOOP_HEADER]], !llvm.loop [[LOOP8:![0-9]+]]451; CHECK: [[EXIT_LOOPEXIT]]:452; CHECK-NEXT: [[FIRST_ADDR_0_LCSSA_I_PH:%.*]] = phi ptr [ [[IV_NEXT]], %[[LOOP_LATCH]] ], [ [[IV]], %[[LOOP_HEADER]] ], [ [[TMP5]], %[[MIDDLE_BLOCK]] ], [ [[TMP14]], %[[VECTOR_EARLY_EXIT]] ]453; CHECK-NEXT: br label %[[EXIT]]454; CHECK: [[EXIT]]:455; CHECK-NEXT: [[FIRST_ADDR_0_LCSSA_I:%.*]] = phi ptr [ [[FIRST]], %[[ENTRY]] ], [ [[FIRST_ADDR_0_LCSSA_I_PH]], %[[EXIT_LOOPEXIT]] ]456; CHECK-NEXT: ret ptr [[FIRST_ADDR_0_LCSSA_I]]457;458entry:459 call void @llvm.assume(i1 true) [ "align"(ptr %first, i64 2) ]460 call void @llvm.assume(i1 true) [ "align"(ptr %last, i64 2) ]461 %last.i64 = ptrtoint ptr %last to i64462 %first.i64 = ptrtoint ptr %first to i64463 %distance = sub i64 %last.i64, %first.i64464 call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %first, i64 %distance) ]465 %c.0 = icmp eq ptr %first, %last466 br i1 %c.0, label %exit, label %loop.header467 468loop.header:469 %iv = phi ptr [ %first, %entry ], [ %iv.next, %loop.latch ]470 %l = load i16, ptr %iv, align 2471 %c.1 = icmp eq i16 %l, 1472 br i1 %c.1, label %exit, label %loop.latch473 474loop.latch:475 %iv.next = getelementptr inbounds nuw i8, ptr %iv, i64 2476 %c.2 = icmp eq ptr %iv.next, %last477 br i1 %c.2, label %exit, label %loop.header478 479exit:480 %first.addr.0.lcssa.i = phi ptr [ %first, %entry ], [ %iv, %loop.header ], [ %iv.next, %loop.latch ]481 ret ptr %first.addr.0.lcssa.i482}483 484; The existing assumptions is strong enough to vectorize this.485define ptr @find_deref_pointer_distance_align_assumption(ptr %first, ptr %last) nofree nosync {486; CHECK-LABEL: define ptr @find_deref_pointer_distance_align_assumption(487; CHECK-SAME: ptr [[FIRST:%.*]], ptr [[LAST:%.*]]) #[[ATTR0]] {488; CHECK-NEXT: [[ENTRY:.*]]:489; CHECK-NEXT: [[LAST_I64:%.*]] = ptrtoint ptr [[LAST]] to i64490; CHECK-NEXT: [[FIRST_I64:%.*]] = ptrtoint ptr [[FIRST]] to i64491; CHECK-NEXT: [[DISTANCE:%.*]] = sub i64 [[LAST_I64]], [[FIRST_I64]]492; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[FIRST]], i64 2) ]493; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[LAST]], i64 2) ]494; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[FIRST]], i64 [[DISTANCE]]) ]495; CHECK-NEXT: [[C_0:%.*]] = icmp eq ptr [[FIRST]], [[LAST]]496; CHECK-NEXT: br i1 [[C_0]], label %[[EXIT:.*]], label %[[LOOP_HEADER_PREHEADER:.*]]497; CHECK: [[LOOP_HEADER_PREHEADER]]:498; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[LAST_I64]], -2499; CHECK-NEXT: [[TMP1:%.*]] = sub i64 [[TMP0]], [[FIRST_I64]]500; CHECK-NEXT: [[TMP2:%.*]] = lshr i64 [[TMP1]], 1501; CHECK-NEXT: [[TMP3:%.*]] = add nuw i64 [[TMP2]], 1502; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP3]], 4503; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]504; CHECK: [[VECTOR_PH]]:505; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[TMP3]], 4506; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP3]], [[N_MOD_VF]]507; CHECK-NEXT: [[TMP4:%.*]] = mul i64 [[N_VEC]], 2508; CHECK-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[FIRST]], i64 [[TMP4]]509; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]510; CHECK: [[VECTOR_BODY]]:511; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]512; CHECK-NEXT: [[OFFSET_IDX:%.*]] = mul i64 [[INDEX]], 2513; CHECK-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr [[FIRST]], i64 [[OFFSET_IDX]]514; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i16>, ptr [[NEXT_GEP]], align 2515; CHECK-NEXT: [[TMP6:%.*]] = icmp eq <4 x i16> [[WIDE_LOAD]], splat (i16 1)516; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4517; CHECK-NEXT: [[TMP7:%.*]] = freeze <4 x i1> [[TMP6]]518; CHECK-NEXT: [[TMP8:%.*]] = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> [[TMP7]])519; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]520; CHECK-NEXT: [[TMP10:%.*]] = or i1 [[TMP8]], [[TMP9]]521; CHECK-NEXT: br i1 [[TMP10]], label %[[MIDDLE_SPLIT:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP9:![0-9]+]]522; CHECK: [[MIDDLE_SPLIT]]:523; CHECK-NEXT: br i1 [[TMP8]], label %[[VECTOR_EARLY_EXIT:.*]], label %[[MIDDLE_BLOCK:.*]]524; CHECK: [[MIDDLE_BLOCK]]:525; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP3]], [[N_VEC]]526; CHECK-NEXT: br i1 [[CMP_N]], label %[[EXIT_LOOPEXIT:.*]], label %[[SCALAR_PH]]527; CHECK: [[VECTOR_EARLY_EXIT]]:528; CHECK-NEXT: [[TMP11:%.*]] = call i64 @llvm.experimental.cttz.elts.i64.v4i1(<4 x i1> [[TMP6]], i1 false)529; CHECK-NEXT: [[TMP12:%.*]] = add i64 [[INDEX]], [[TMP11]]530; CHECK-NEXT: [[TMP13:%.*]] = mul i64 [[TMP12]], 2531; CHECK-NEXT: [[TMP14:%.*]] = getelementptr i8, ptr [[FIRST]], i64 [[TMP13]]532; CHECK-NEXT: br label %[[EXIT_LOOPEXIT]]533; CHECK: [[SCALAR_PH]]:534; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi ptr [ [[TMP5]], %[[MIDDLE_BLOCK]] ], [ [[FIRST]], %[[LOOP_HEADER_PREHEADER]] ]535; CHECK-NEXT: br label %[[LOOP_HEADER:.*]]536; CHECK: [[LOOP_HEADER]]:537; CHECK-NEXT: [[IV:%.*]] = phi ptr [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ], [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ]538; CHECK-NEXT: [[L:%.*]] = load i16, ptr [[IV]], align 2539; CHECK-NEXT: [[C_1:%.*]] = icmp eq i16 [[L]], 1540; CHECK-NEXT: br i1 [[C_1]], label %[[EXIT_LOOPEXIT]], label %[[LOOP_LATCH]]541; CHECK: [[LOOP_LATCH]]:542; CHECK-NEXT: [[IV_NEXT]] = getelementptr inbounds nuw i8, ptr [[IV]], i64 2543; CHECK-NEXT: [[C_2:%.*]] = icmp eq ptr [[IV_NEXT]], [[LAST]]544; CHECK-NEXT: br i1 [[C_2]], label %[[EXIT_LOOPEXIT]], label %[[LOOP_HEADER]], !llvm.loop [[LOOP10:![0-9]+]]545; CHECK: [[EXIT_LOOPEXIT]]:546; CHECK-NEXT: [[FIRST_ADDR_0_LCSSA_I_PH:%.*]] = phi ptr [ [[IV_NEXT]], %[[LOOP_LATCH]] ], [ [[IV]], %[[LOOP_HEADER]] ], [ [[TMP5]], %[[MIDDLE_BLOCK]] ], [ [[TMP14]], %[[VECTOR_EARLY_EXIT]] ]547; CHECK-NEXT: br label %[[EXIT]]548; CHECK: [[EXIT]]:549; CHECK-NEXT: [[FIRST_ADDR_0_LCSSA_I:%.*]] = phi ptr [ [[FIRST]], %[[ENTRY]] ], [ [[FIRST_ADDR_0_LCSSA_I_PH]], %[[EXIT_LOOPEXIT]] ]550; CHECK-NEXT: ret ptr [[FIRST_ADDR_0_LCSSA_I]]551;552entry:553 %last.i64 = ptrtoint ptr %last to i64554 %first.i64 = ptrtoint ptr %first to i64555 %distance = sub i64 %last.i64, %first.i64556 call void @llvm.assume(i1 true) [ "align"(ptr %first, i64 2) ]557 call void @llvm.assume(i1 true) [ "align"(ptr %last, i64 2) ]558 call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %first, i64 %distance) ]559 %c.0 = icmp eq ptr %first, %last560 br i1 %c.0, label %exit, label %loop.header561 562loop.header:563 %iv = phi ptr [ %first, %entry ], [ %iv.next, %loop.latch ]564 %l = load i16, ptr %iv, align 2565 %c.1 = icmp eq i16 %l, 1566 br i1 %c.1, label %exit, label %loop.latch567 568loop.latch:569 %iv.next = getelementptr inbounds nuw i8, ptr %iv, i64 2570 %c.2 = icmp eq ptr %iv.next, %last571 br i1 %c.2, label %exit, label %loop.header572 573exit:574 %first.addr.0.lcssa.i = phi ptr [ %first, %entry ], [ %iv, %loop.header ], [ %iv.next, %loop.latch ]575 ret ptr %first.addr.0.lcssa.i576}577 578define i64 @early_exit_alignment_and_deref_known_via_assumption_with_constant_size_nofree_via_context(ptr noalias %p1, ptr noalias %p2) nosync {579; CHECK-LABEL: define i64 @early_exit_alignment_and_deref_known_via_assumption_with_constant_size_nofree_via_context(580; CHECK-SAME: ptr noalias [[P1:%.*]], ptr noalias [[P2:%.*]]) #[[ATTR1:[0-9]+]] {581; CHECK-NEXT: [[ENTRY:.*:]]582; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[P1]], i64 4), "dereferenceable"(ptr [[P1]], i64 1024) ]583; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[P2]], i64 4), "dereferenceable"(ptr [[P2]], i64 1024) ]584; CHECK-NEXT: br label %[[VECTOR_PH:.*]]585; CHECK: [[VECTOR_PH]]:586; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]587; CHECK: [[VECTOR_BODY]]:588; CHECK-NEXT: [[INDEX1:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT3:%.*]], %[[VECTOR_BODY]] ]589; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[INDEX1]]590; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i8>, ptr [[ARRAYIDX2]], align 1591; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 [[INDEX1]]592; CHECK-NEXT: [[WIDE_LOAD2:%.*]] = load <4 x i8>, ptr [[TMP1]], align 1593; CHECK-NEXT: [[TMP2:%.*]] = icmp ne <4 x i8> [[WIDE_LOAD]], [[WIDE_LOAD2]]594; CHECK-NEXT: [[INDEX_NEXT3]] = add nuw i64 [[INDEX1]], 4595; CHECK-NEXT: [[TMP3:%.*]] = freeze <4 x i1> [[TMP2]]596; CHECK-NEXT: [[TMP4:%.*]] = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> [[TMP3]])597; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i64 [[INDEX_NEXT3]], 1024598; CHECK-NEXT: [[TMP6:%.*]] = or i1 [[TMP4]], [[TMP5]]599; CHECK-NEXT: br i1 [[TMP6]], label %[[MIDDLE_SPLIT:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP11:![0-9]+]]600; CHECK: [[MIDDLE_SPLIT]]:601; CHECK-NEXT: br i1 [[TMP4]], label %[[VECTOR_EARLY_EXIT:.*]], label %[[MIDDLE_BLOCK:.*]]602; CHECK: [[MIDDLE_BLOCK]]:603; CHECK-NEXT: br label %[[LOOP_END:.*]]604; CHECK: [[VECTOR_EARLY_EXIT]]:605; CHECK-NEXT: [[TMP7:%.*]] = call i64 @llvm.experimental.cttz.elts.i64.v4i1(<4 x i1> [[TMP2]], i1 false)606; CHECK-NEXT: [[TMP8:%.*]] = add i64 [[INDEX1]], [[TMP7]]607; CHECK-NEXT: br label %[[LOOP_END]]608; CHECK: [[LOOP_END]]:609; CHECK-NEXT: [[RETVAL:%.*]] = phi i64 [ -1, %[[MIDDLE_BLOCK]] ], [ [[TMP8]], %[[VECTOR_EARLY_EXIT]] ]610; CHECK-NEXT: ret i64 [[RETVAL]]611;612entry:613 call void @llvm.assume(i1 true) [ "align"(ptr %p1, i64 4), "dereferenceable"(ptr %p1, i64 1024) ]614 call void @llvm.assume(i1 true) [ "align"(ptr %p2, i64 4), "dereferenceable"(ptr %p2, i64 1024) ]615 br label %loop616 617loop:618 %index = phi i64 [ %index.next, %loop.inc ], [ 0, %entry ]619 %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index620 %ld1 = load i8, ptr %arrayidx, align 1621 %arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index622 %ld2 = load i8, ptr %arrayidx1, align 1623 %cmp3 = icmp eq i8 %ld1, %ld2624 br i1 %cmp3, label %loop.inc, label %loop.end625 626loop.inc:627 %index.next = add i64 %index, 1628 %exitcond = icmp ne i64 %index.next, 1024629 br i1 %exitcond, label %loop, label %loop.end630 631loop.end:632 %retval = phi i64 [ %index, %loop ], [ -1, %loop.inc ]633 ret i64 %retval634}635 636; Test with an invoke terminator between the block containing the assume and loop.637; This should NOT vectorize because the invoke could free memory.638define i64 @early_exit_alignment_and_deref_known_via_assumption_with_constant_size_invoke_may_free(ptr noalias %p1, ptr noalias %p2) nosync personality ptr @__gxx_personality_v0 {639; CHECK-LABEL: define i64 @early_exit_alignment_and_deref_known_via_assumption_with_constant_size_invoke_may_free(640; CHECK-SAME: ptr noalias [[P1:%.*]], ptr noalias [[P2:%.*]]) #[[ATTR1]] personality ptr @__gxx_personality_v0 {641; CHECK-NEXT: [[ENTRY:.*:]]642; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[P1]], i64 4), "dereferenceable"(ptr [[P1]], i64 1024) ]643; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[P2]], i64 4), "dereferenceable"(ptr [[P2]], i64 1024) ]644; CHECK-NEXT: invoke void @may_free()645; CHECK-NEXT: to label %[[LOOP_PREHEADER:.*]] unwind label %[[LPAD:.*]]646; CHECK: [[LOOP_PREHEADER]]:647; CHECK-NEXT: br label %[[LOOP:.*]]648; CHECK: [[LOOP]]:649; CHECK-NEXT: [[INDEX1:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], %[[LOOP_INC:.*]] ], [ 0, %[[LOOP_PREHEADER]] ]650; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[INDEX1]]651; CHECK-NEXT: [[LD1:%.*]] = load i8, ptr [[TMP0]], align 1652; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 [[INDEX1]]653; CHECK-NEXT: [[LD2:%.*]] = load i8, ptr [[TMP1]], align 1654; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i8 [[LD1]], [[LD2]]655; CHECK-NEXT: br i1 [[CMP3]], label %[[LOOP_INC]], label %[[LOOP_END:.*]]656; CHECK: [[LOOP_INC]]:657; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX1]], 1658; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], 1024659; CHECK-NEXT: br i1 [[EXITCOND]], label %[[LOOP]], label %[[LOOP_END]]660; CHECK: [[LOOP_END]]:661; CHECK-NEXT: [[RETVAL:%.*]] = phi i64 [ [[INDEX1]], %[[LOOP]] ], [ -1, %[[LOOP_INC]] ]662; CHECK-NEXT: ret i64 [[RETVAL]]663; CHECK: [[LPAD]]:664; CHECK-NEXT: [[LP:%.*]] = landingpad { ptr, i32 }665; CHECK-NEXT: cleanup666; CHECK-NEXT: resume { ptr, i32 } [[LP]]667;668entry:669 call void @llvm.assume(i1 true) [ "align"(ptr %p1, i64 4), "dereferenceable"(ptr %p1, i64 1024) ]670 call void @llvm.assume(i1 true) [ "align"(ptr %p2, i64 4), "dereferenceable"(ptr %p2, i64 1024) ]671 invoke void @may_free() to label %loop unwind label %lpad672 673loop:674 %index = phi i64 [ %index.next, %loop.inc ], [ 0, %entry ]675 %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index676 %ld1 = load i8, ptr %arrayidx, align 1677 %arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index678 %ld2 = load i8, ptr %arrayidx1, align 1679 %cmp3 = icmp eq i8 %ld1, %ld2680 br i1 %cmp3, label %loop.inc, label %loop.end681 682loop.inc:683 %index.next = add i64 %index, 1684 %exitcond = icmp ne i64 %index.next, 1024685 br i1 %exitcond, label %loop, label %loop.end686 687loop.end:688 %retval = phi i64 [ %index, %loop ], [ -1, %loop.inc ]689 ret i64 %retval690 691lpad:692 %lp = landingpad { ptr, i32 } cleanup693 resume { ptr, i32 } %lp694}695 696define i64 @find_if_pointer_distance_deref_via_assumption(ptr %vec) nofree nosync {697; CHECK-LABEL: define i64 @find_if_pointer_distance_deref_via_assumption(698; CHECK-SAME: ptr [[VEC:%.*]]) #[[ATTR0]] {699; CHECK-NEXT: [[ENTRY:.*]]:700; CHECK-NEXT: [[BEGIN:%.*]] = load ptr, ptr [[VEC]], align 8701; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[BEGIN]], i64 2) ]702; CHECK-NEXT: [[BEGIN_INT:%.*]] = ptrtoint ptr [[BEGIN]] to i64703; CHECK-NEXT: [[END_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[VEC]], i64 8704; CHECK-NEXT: [[END:%.*]] = load ptr, ptr [[END_GEP]], align 8705; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[END]], i64 2) ]706; CHECK-NEXT: [[END_INT:%.*]] = ptrtoint ptr [[END]] to i64707; CHECK-NEXT: [[DISTANCE:%.*]] = sub i64 [[END_INT]], [[BEGIN_INT]]708; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[BEGIN]], i64 [[DISTANCE]]) ]709; CHECK-NEXT: [[IS_EMPTY:%.*]] = icmp eq ptr [[BEGIN]], [[END]]710; CHECK-NEXT: br i1 [[IS_EMPTY]], label %[[EXIT:.*]], label %[[LOOP_PREHEADER:.*]]711; CHECK: [[LOOP_PREHEADER]]:712; CHECK-NEXT: [[END_PTR:%.*]] = getelementptr i8, ptr [[BEGIN]], i64 [[DISTANCE]]713; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[END_INT]], -2714; CHECK-NEXT: [[TMP1:%.*]] = sub i64 [[TMP0]], [[BEGIN_INT]]715; CHECK-NEXT: [[TMP2:%.*]] = lshr i64 [[TMP1]], 1716; CHECK-NEXT: [[TMP3:%.*]] = add nuw i64 [[TMP2]], 1717; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP3]], 4718; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]719; CHECK: [[VECTOR_PH]]:720; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[TMP3]], 4721; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP3]], [[N_MOD_VF]]722; CHECK-NEXT: [[TMP4:%.*]] = mul i64 [[N_VEC]], 2723; CHECK-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[BEGIN]], i64 [[TMP4]]724; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]725; CHECK: [[VECTOR_BODY]]:726; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]727; CHECK-NEXT: [[OFFSET_IDX:%.*]] = mul i64 [[INDEX]], 2728; CHECK-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr [[BEGIN]], i64 [[OFFSET_IDX]]729; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i16>, ptr [[NEXT_GEP]], align 2730; CHECK-NEXT: [[TMP6:%.*]] = icmp eq <4 x i16> [[WIDE_LOAD]], splat (i16 1)731; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4732; CHECK-NEXT: [[TMP7:%.*]] = freeze <4 x i1> [[TMP6]]733; CHECK-NEXT: [[TMP8:%.*]] = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> [[TMP7]])734; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]735; CHECK-NEXT: [[TMP10:%.*]] = or i1 [[TMP8]], [[TMP9]]736; CHECK-NEXT: br i1 [[TMP10]], label %[[MIDDLE_SPLIT:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP12:![0-9]+]]737; CHECK: [[MIDDLE_SPLIT]]:738; CHECK-NEXT: br i1 [[TMP8]], label %[[VECTOR_EARLY_EXIT:.*]], label %[[MIDDLE_BLOCK:.*]]739; CHECK: [[MIDDLE_BLOCK]]:740; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP3]], [[N_VEC]]741; CHECK-NEXT: br i1 [[CMP_N]], label %[[EXIT_LOOPEXIT:.*]], label %[[SCALAR_PH]]742; CHECK: [[VECTOR_EARLY_EXIT]]:743; CHECK-NEXT: [[TMP11:%.*]] = call i64 @llvm.experimental.cttz.elts.i64.v4i1(<4 x i1> [[TMP6]], i1 false)744; CHECK-NEXT: [[TMP12:%.*]] = add i64 [[INDEX]], [[TMP11]]745; CHECK-NEXT: [[TMP13:%.*]] = mul i64 [[TMP12]], 2746; CHECK-NEXT: [[TMP14:%.*]] = getelementptr i8, ptr [[BEGIN]], i64 [[TMP13]]747; CHECK-NEXT: br label %[[EXIT_LOOPEXIT]]748; CHECK: [[SCALAR_PH]]:749; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi ptr [ [[TMP5]], %[[MIDDLE_BLOCK]] ], [ [[BEGIN]], %[[LOOP_PREHEADER]] ]750; CHECK-NEXT: br label %[[LOOP_HEADER:.*]]751; CHECK: [[LOOP_HEADER]]:752; CHECK-NEXT: [[PTR:%.*]] = phi ptr [ [[PTR_NEXT:%.*]], %[[LOOP_LATCH:.*]] ], [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ]753; CHECK-NEXT: [[VAL:%.*]] = load i16, ptr [[PTR]], align 2754; CHECK-NEXT: [[FOUND:%.*]] = icmp eq i16 [[VAL]], 1755; CHECK-NEXT: br i1 [[FOUND]], label %[[EXIT_LOOPEXIT]], label %[[LOOP_LATCH]]756; CHECK: [[LOOP_LATCH]]:757; CHECK-NEXT: [[PTR_NEXT]] = getelementptr inbounds nuw i8, ptr [[PTR]], i64 2758; CHECK-NEXT: [[DONE:%.*]] = icmp eq ptr [[PTR_NEXT]], [[END]]759; CHECK-NEXT: br i1 [[DONE]], label %[[EXIT_LOOPEXIT]], label %[[LOOP_HEADER]], !llvm.loop [[LOOP13:![0-9]+]]760; CHECK: [[EXIT_LOOPEXIT]]:761; CHECK-NEXT: [[RESULT_PH:%.*]] = phi ptr [ [[END_PTR]], %[[LOOP_LATCH]] ], [ [[PTR]], %[[LOOP_HEADER]] ], [ [[END_PTR]], %[[MIDDLE_BLOCK]] ], [ [[TMP14]], %[[VECTOR_EARLY_EXIT]] ]762; CHECK-NEXT: [[DOTRESULT_INT:%.*]] = ptrtoint ptr [[RESULT_PH]] to i64763; CHECK-NEXT: br label %[[EXIT]]764; CHECK: [[EXIT]]:765; CHECK-NEXT: [[RESULT_INT:%.*]] = phi i64 [ [[DOTRESULT_INT]], %[[EXIT_LOOPEXIT]] ], [ [[BEGIN_INT]], %[[ENTRY]] ]766; CHECK-NEXT: ret i64 [[RESULT_INT]]767;768entry:769 %begin = load ptr, ptr %vec, align 8770 call void @llvm.assume(i1 true) [ "align"(ptr %begin, i64 2) ]771 %begin.int = ptrtoint ptr %begin to i64772 %end.gep = getelementptr inbounds nuw i8, ptr %vec, i64 8773 %end = load ptr, ptr %end.gep, align 8774 call void @llvm.assume(i1 true) [ "align"(ptr %end, i64 2) ]775 %end.int = ptrtoint ptr %end to i64776 %distance = sub i64 %end.int, %begin.int777 call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %begin, i64 %distance) ]778 %is.empty = icmp eq ptr %begin, %end779 br i1 %is.empty, label %exit, label %loop.preheader780 781loop.preheader:782 %end.ptr = getelementptr i8, ptr %begin, i64 %distance783 br label %loop.header784 785loop.header:786 %ptr = phi ptr [ %ptr.next, %loop.latch ], [ %begin, %loop.preheader ]787 %val = load i16, ptr %ptr, align 2788 %found = icmp eq i16 %val, 1789 br i1 %found, label %exit.loopexit, label %loop.latch790 791loop.latch:792 %ptr.next = getelementptr inbounds nuw i8, ptr %ptr, i64 2793 %done = icmp eq ptr %ptr.next, %end794 br i1 %done, label %exit.loopexit, label %loop.header795 796exit.loopexit:797 %result.ph = phi ptr [ %end.ptr, %loop.latch ], [ %ptr, %loop.header ]798 %.result.int = ptrtoint ptr %result.ph to i64799 br label %exit800 801exit:802 %result.int = phi i64 [ %.result.int, %exit.loopexit ], [ %begin.int, %entry ]803 ret i64 %result.int804}805 806declare void @may_free()807 808define i64 @find_if_pointer_distance_deref_via_assumption_mayfree_call(ptr %vec) nofree {809; CHECK-LABEL: define i64 @find_if_pointer_distance_deref_via_assumption_mayfree_call(810; CHECK-SAME: ptr [[VEC:%.*]]) #[[ATTR2:[0-9]+]] {811; CHECK-NEXT: [[ENTRY:.*]]:812; CHECK-NEXT: [[BEGIN:%.*]] = load ptr, ptr [[VEC]], align 8813; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[BEGIN]], i64 2) ]814; CHECK-NEXT: [[BEGIN_INT:%.*]] = ptrtoint ptr [[BEGIN]] to i64815; CHECK-NEXT: [[END_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[VEC]], i64 8816; CHECK-NEXT: [[END:%.*]] = load ptr, ptr [[END_GEP]], align 8817; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[END]], i64 2) ]818; CHECK-NEXT: [[END_INT:%.*]] = ptrtoint ptr [[END]] to i64819; CHECK-NEXT: [[DISTANCE:%.*]] = sub i64 [[END_INT]], [[BEGIN_INT]]820; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[BEGIN]], i64 [[DISTANCE]]) ]821; CHECK-NEXT: [[IS_EMPTY:%.*]] = icmp eq ptr [[BEGIN]], [[END]]822; CHECK-NEXT: br i1 [[IS_EMPTY]], label %[[EXIT:.*]], label %[[LOOP_PREHEADER:.*]]823; CHECK: [[LOOP_PREHEADER]]:824; CHECK-NEXT: call void @may_free()825; CHECK-NEXT: [[END_PTR:%.*]] = getelementptr i8, ptr [[BEGIN]], i64 [[DISTANCE]]826; CHECK-NEXT: br label %[[LOOP:.*]]827; CHECK: [[LOOP]]:828; CHECK-NEXT: [[PTR:%.*]] = phi ptr [ [[PTR_NEXT:%.*]], %[[LOOP_INC:.*]] ], [ [[BEGIN]], %[[LOOP_PREHEADER]] ]829; CHECK-NEXT: [[VAL:%.*]] = load i16, ptr [[PTR]], align 2830; CHECK-NEXT: [[FOUND:%.*]] = icmp eq i16 [[VAL]], 1831; CHECK-NEXT: br i1 [[FOUND]], label %[[EXIT_LOOPEXIT:.*]], label %[[LOOP_INC]]832; CHECK: [[LOOP_INC]]:833; CHECK-NEXT: [[PTR_NEXT]] = getelementptr inbounds nuw i8, ptr [[PTR]], i64 2834; CHECK-NEXT: [[DONE:%.*]] = icmp eq ptr [[PTR_NEXT]], [[END]]835; CHECK-NEXT: br i1 [[DONE]], label %[[EXIT_LOOPEXIT]], label %[[LOOP]]836; CHECK: [[EXIT_LOOPEXIT]]:837; CHECK-NEXT: [[RESULT_PH:%.*]] = phi ptr [ [[END_PTR]], %[[LOOP_INC]] ], [ [[PTR]], %[[LOOP]] ]838; CHECK-NEXT: [[DOTRESULT_INT:%.*]] = ptrtoint ptr [[RESULT_PH]] to i64839; CHECK-NEXT: br label %[[EXIT]]840; CHECK: [[EXIT]]:841; CHECK-NEXT: [[RESULT_INT:%.*]] = phi i64 [ [[DOTRESULT_INT]], %[[EXIT_LOOPEXIT]] ], [ [[BEGIN_INT]], %[[ENTRY]] ]842; CHECK-NEXT: ret i64 [[RESULT_INT]]843;844entry:845 %begin = load ptr, ptr %vec, align 8846 call void @llvm.assume(i1 true) [ "align"(ptr %begin, i64 2) ]847 %begin.int = ptrtoint ptr %begin to i64848 %end.gep = getelementptr inbounds nuw i8, ptr %vec, i64 8849 %end = load ptr, ptr %end.gep, align 8850 call void @llvm.assume(i1 true) [ "align"(ptr %end, i64 2) ]851 %end.int = ptrtoint ptr %end to i64852 %distance = sub i64 %end.int, %begin.int853 call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %begin, i64 %distance) ]854 %is.empty = icmp eq ptr %begin, %end855 br i1 %is.empty, label %exit, label %loop.preheader856 857loop.preheader:858 call void @may_free()859 %end.ptr = getelementptr i8, ptr %begin, i64 %distance860 br label %loop861 862loop:863 %ptr = phi ptr [ %ptr.next, %loop.inc ], [ %begin, %loop.preheader ]864 %val = load i16, ptr %ptr, align 2865 %found = icmp eq i16 %val, 1866 br i1 %found, label %exit.loopexit, label %loop.inc867 868loop.inc:869 %ptr.next = getelementptr inbounds nuw i8, ptr %ptr, i64 2870 %done = icmp eq ptr %ptr.next, %end871 br i1 %done, label %exit.loopexit, label %loop872 873exit.loopexit:874 %result.ph = phi ptr [ %end.ptr, %loop.inc ], [ %ptr, %loop ]875 %.result.int = ptrtoint ptr %result.ph to i64876 br label %exit877 878exit:879 %result.int = phi i64 [ %.result.int, %exit.loopexit ], [ %begin.int, %entry ]880 ret i64 %result.int881}882 883; Test with an invoke terminator between the block containing the assume and loop.884; This should NOT vectorize because the invoke could free memory.885define i64 @find_if_deref_via_assumption_invoke_may_free_in_assume_block(ptr %vec) nofree nosync personality ptr @__gxx_personality_v0 {886; CHECK-LABEL: define i64 @find_if_deref_via_assumption_invoke_may_free_in_assume_block(887; CHECK-SAME: ptr [[VEC:%.*]]) #[[ATTR0]] personality ptr @__gxx_personality_v0 {888; CHECK-NEXT: [[ENTRY:.*:]]889; CHECK-NEXT: [[BEGIN:%.*]] = load ptr, ptr [[VEC]], align 8890; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[BEGIN]], i64 2) ]891; CHECK-NEXT: [[BEGIN_INT:%.*]] = ptrtoint ptr [[BEGIN]] to i64892; CHECK-NEXT: [[END_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[VEC]], i64 8893; CHECK-NEXT: [[END:%.*]] = load ptr, ptr [[END_GEP]], align 8894; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[END]], i64 2) ]895; CHECK-NEXT: [[END_INT:%.*]] = ptrtoint ptr [[END]] to i64896; CHECK-NEXT: [[DISTANCE:%.*]] = sub i64 [[END_INT]], [[BEGIN_INT]]897; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[BEGIN]], i64 [[DISTANCE]]) ]898; CHECK-NEXT: [[NOT_EMPTY:%.*]] = icmp ne ptr [[BEGIN]], [[END]]899; CHECK-NEXT: call void @llvm.assume(i1 [[NOT_EMPTY]])900; CHECK-NEXT: invoke void @may_free()901; CHECK-NEXT: to label %[[LOOP_PREHEADER:.*]] unwind label %[[LPAD:.*]]902; CHECK: [[LOOP_PREHEADER]]:903; CHECK-NEXT: [[END_PTR:%.*]] = getelementptr i8, ptr [[BEGIN]], i64 [[DISTANCE]]904; CHECK-NEXT: br label %[[LOOP:.*]]905; CHECK: [[LOOP]]:906; CHECK-NEXT: [[PTR:%.*]] = phi ptr [ [[PTR_NEXT:%.*]], %[[LOOP_INC:.*]] ], [ [[BEGIN]], %[[LOOP_PREHEADER]] ]907; CHECK-NEXT: [[VAL:%.*]] = load i16, ptr [[PTR]], align 2908; CHECK-NEXT: [[FOUND:%.*]] = icmp eq i16 [[VAL]], 1909; CHECK-NEXT: br i1 [[FOUND]], label %[[EXIT_LOOPEXIT:.*]], label %[[LOOP_INC]]910; CHECK: [[LOOP_INC]]:911; CHECK-NEXT: [[PTR_NEXT]] = getelementptr inbounds nuw i8, ptr [[PTR]], i64 2912; CHECK-NEXT: [[DONE:%.*]] = icmp eq ptr [[PTR_NEXT]], [[END]]913; CHECK-NEXT: br i1 [[DONE]], label %[[EXIT_LOOPEXIT]], label %[[LOOP]]914; CHECK: [[LPAD]]:915; CHECK-NEXT: [[LP:%.*]] = landingpad { ptr, i32 }916; CHECK-NEXT: cleanup917; CHECK-NEXT: resume { ptr, i32 } [[LP]]918; CHECK: [[EXIT_LOOPEXIT]]:919; CHECK-NEXT: [[RESULT_PH:%.*]] = phi ptr [ [[END_PTR]], %[[LOOP_INC]] ], [ [[PTR]], %[[LOOP]] ]920; CHECK-NEXT: [[DOTRESULT_INT:%.*]] = ptrtoint ptr [[RESULT_PH]] to i64921; CHECK-NEXT: br label %[[EXIT:.*]]922; CHECK: [[EXIT]]:923; CHECK-NEXT: [[RESULT_INT:%.*]] = phi i64 [ [[DOTRESULT_INT]], %[[EXIT_LOOPEXIT]] ]924; CHECK-NEXT: ret i64 [[RESULT_INT]]925;926entry:927 %begin = load ptr, ptr %vec, align 8928 call void @llvm.assume(i1 true) [ "align"(ptr %begin, i64 2) ]929 %begin.int = ptrtoint ptr %begin to i64930 %end.gep = getelementptr inbounds nuw i8, ptr %vec, i64 8931 %end = load ptr, ptr %end.gep, align 8932 call void @llvm.assume(i1 true) [ "align"(ptr %end, i64 2) ]933 %end.int = ptrtoint ptr %end to i64934 %distance = sub i64 %end.int, %begin.int935 call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %begin, i64 %distance) ]936 %not.empty = icmp ne ptr %begin, %end937 call void @llvm.assume(i1 %not.empty)938 invoke void @may_free() to label %loop.preheader unwind label %lpad939 940loop.preheader:941 %end.ptr = getelementptr i8, ptr %begin, i64 %distance942 br label %loop943 944loop:945 %ptr = phi ptr [ %ptr.next, %loop.inc ], [ %begin, %loop.preheader ]946 %val = load i16, ptr %ptr, align 2947 %found = icmp eq i16 %val, 1948 br i1 %found, label %exit.loopexit, label %loop.inc949 950loop.inc:951 %ptr.next = getelementptr inbounds nuw i8, ptr %ptr, i64 2952 %done = icmp eq ptr %ptr.next, %end953 br i1 %done, label %exit.loopexit, label %loop954 955lpad:956 %lp = landingpad { ptr, i32 } cleanup957 resume { ptr, i32 } %lp958 959exit.loopexit:960 %result.ph = phi ptr [ %end.ptr, %loop.inc ], [ %ptr, %loop ]961 %.result.int = ptrtoint ptr %result.ph to i64962 br label %exit963 964exit:965 %result.int = phi i64 [ %.result.int, %exit.loopexit ]966 ret i64 %result.int967}968 969; Test with an invoke terminator between the block containing the assume and loop.970; This should NOT vectorize because the invoke could free memory.971define i64 @find_if_deref_via_assumption_invoke_may_free_in_preheader(ptr %vec) nofree nosync personality ptr @__gxx_personality_v0 {972; CHECK-LABEL: define i64 @find_if_deref_via_assumption_invoke_may_free_in_preheader(973; CHECK-SAME: ptr [[VEC:%.*]]) #[[ATTR0]] personality ptr @__gxx_personality_v0 {974; CHECK-NEXT: [[ENTRY:.*]]:975; CHECK-NEXT: [[BEGIN:%.*]] = load ptr, ptr [[VEC]], align 8976; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[BEGIN]], i64 2) ]977; CHECK-NEXT: [[BEGIN_INT:%.*]] = ptrtoint ptr [[BEGIN]] to i64978; CHECK-NEXT: [[END_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[VEC]], i64 8979; CHECK-NEXT: [[END:%.*]] = load ptr, ptr [[END_GEP]], align 8980; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[END]], i64 2) ]981; CHECK-NEXT: [[END_INT:%.*]] = ptrtoint ptr [[END]] to i64982; CHECK-NEXT: [[DISTANCE:%.*]] = sub i64 [[END_INT]], [[BEGIN_INT]]983; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[BEGIN]], i64 [[DISTANCE]]) ]984; CHECK-NEXT: [[IS_EMPTY:%.*]] = icmp eq ptr [[BEGIN]], [[END]]985; CHECK-NEXT: br i1 [[IS_EMPTY]], label %[[EXIT:.*]], label %[[LOOP_PREHEADER:.*]]986; CHECK: [[LOOP_PREHEADER]]:987; CHECK-NEXT: [[END_PTR:%.*]] = getelementptr i8, ptr [[BEGIN]], i64 [[DISTANCE]]988; CHECK-NEXT: invoke void @may_free()989; CHECK-NEXT: to label %[[LOOP_PREHEADER1:.*]] unwind label %[[LPAD:.*]]990; CHECK: [[LOOP_PREHEADER1]]:991; CHECK-NEXT: br label %[[LOOP:.*]]992; CHECK: [[LOOP]]:993; CHECK-NEXT: [[PTR:%.*]] = phi ptr [ [[PTR_NEXT:%.*]], %[[LOOP_INC:.*]] ], [ [[BEGIN]], %[[LOOP_PREHEADER1]] ]994; CHECK-NEXT: [[VAL:%.*]] = load i16, ptr [[PTR]], align 2995; CHECK-NEXT: [[FOUND:%.*]] = icmp eq i16 [[VAL]], 1996; CHECK-NEXT: br i1 [[FOUND]], label %[[EXIT_LOOPEXIT:.*]], label %[[LOOP_INC]]997; CHECK: [[LOOP_INC]]:998; CHECK-NEXT: [[PTR_NEXT]] = getelementptr inbounds nuw i8, ptr [[PTR]], i64 2999; CHECK-NEXT: [[DONE:%.*]] = icmp eq ptr [[PTR_NEXT]], [[END]]1000; CHECK-NEXT: br i1 [[DONE]], label %[[EXIT_LOOPEXIT]], label %[[LOOP]]1001; CHECK: [[LPAD]]:1002; CHECK-NEXT: [[LP:%.*]] = landingpad { ptr, i32 }1003; CHECK-NEXT: cleanup1004; CHECK-NEXT: resume { ptr, i32 } [[LP]]1005; CHECK: [[EXIT_LOOPEXIT]]:1006; CHECK-NEXT: [[RESULT_PH:%.*]] = phi ptr [ [[END_PTR]], %[[LOOP_INC]] ], [ [[PTR]], %[[LOOP]] ]1007; CHECK-NEXT: [[DOTRESULT_INT:%.*]] = ptrtoint ptr [[RESULT_PH]] to i641008; CHECK-NEXT: br label %[[EXIT]]1009; CHECK: [[EXIT]]:1010; CHECK-NEXT: [[RESULT_INT:%.*]] = phi i64 [ [[DOTRESULT_INT]], %[[EXIT_LOOPEXIT]] ], [ [[BEGIN_INT]], %[[ENTRY]] ]1011; CHECK-NEXT: ret i64 [[RESULT_INT]]1012;1013entry:1014 %begin = load ptr, ptr %vec, align 81015 call void @llvm.assume(i1 true) [ "align"(ptr %begin, i64 2) ]1016 %begin.int = ptrtoint ptr %begin to i641017 %end.gep = getelementptr inbounds nuw i8, ptr %vec, i64 81018 %end = load ptr, ptr %end.gep, align 81019 call void @llvm.assume(i1 true) [ "align"(ptr %end, i64 2) ]1020 %end.int = ptrtoint ptr %end to i641021 %distance = sub i64 %end.int, %begin.int1022 call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %begin, i64 %distance) ]1023 %is.empty = icmp eq ptr %begin, %end1024 br i1 %is.empty, label %exit, label %loop.preheader1025 1026loop.preheader:1027 %end.ptr = getelementptr i8, ptr %begin, i64 %distance1028 invoke void @may_free() to label %loop unwind label %lpad1029 1030loop:1031 %ptr = phi ptr [ %ptr.next, %loop.inc ], [ %begin, %loop.preheader ]1032 %val = load i16, ptr %ptr, align 21033 %found = icmp eq i16 %val, 11034 br i1 %found, label %exit.loopexit, label %loop.inc1035 1036loop.inc:1037 %ptr.next = getelementptr inbounds nuw i8, ptr %ptr, i64 21038 %done = icmp eq ptr %ptr.next, %end1039 br i1 %done, label %exit.loopexit, label %loop1040 1041lpad:1042 %lp = landingpad { ptr, i32 } cleanup1043 resume { ptr, i32 } %lp1044 1045exit.loopexit:1046 %result.ph = phi ptr [ %end.ptr, %loop.inc ], [ %ptr, %loop ]1047 %.result.int = ptrtoint ptr %result.ph to i641048 br label %exit1049 1050exit:1051 %result.int = phi i64 [ %.result.int, %exit.loopexit ], [ %begin.int, %entry ]1052 ret i64 %result.int1053}1054 1055declare i32 @__gxx_personality_v0(...)1056