brintos

brintos / llvm-project-archived public Read only

0
0
Text · 55.4 KiB · 0bc2748 Raw
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