647 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals none --version 52; RUN: opt -passes=loop-vectorize -force-vector-width=4 -force-vector-interleave=1 -S %s | FileCheck %s3 4; Test cases for selecting the index with the minimum value.5 6define i64 @test_vectorize_select_umin_idx(ptr %src, i64 %n) {7; CHECK-LABEL: define i64 @test_vectorize_select_umin_idx(8; CHECK-SAME: ptr [[SRC:%.*]], i64 [[N:%.*]]) {9; CHECK-NEXT: [[ENTRY:.*]]:10; CHECK-NEXT: br label %[[LOOP:.*]]11; CHECK: [[LOOP]]:12; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]13; CHECK-NEXT: [[MIN_IDX:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[MIN_IDX_NEXT:%.*]], %[[LOOP]] ]14; CHECK-NEXT: [[MIN_VAL:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[MIN_VAL_NEXT:%.*]], %[[LOOP]] ]15; CHECK-NEXT: [[GEP:%.*]] = getelementptr i64, ptr [[SRC]], i64 [[IV]]16; CHECK-NEXT: [[L:%.*]] = load i64, ptr [[GEP]], align 417; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[MIN_VAL]], [[L]]18; CHECK-NEXT: [[MIN_VAL_NEXT]] = tail call i64 @llvm.umin.i64(i64 [[MIN_VAL]], i64 [[L]])19; CHECK-NEXT: [[MIN_IDX_NEXT]] = select i1 [[CMP]], i64 [[IV]], i64 [[MIN_IDX]]20; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 121; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV_NEXT]], [[N]]22; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[EXIT:.*]], label %[[LOOP]]23; CHECK: [[EXIT]]:24; CHECK-NEXT: [[RES:%.*]] = phi i64 [ [[MIN_IDX_NEXT]], %[[LOOP]] ]25; CHECK-NEXT: ret i64 [[RES]]26;27entry:28 br label %loop29 30loop:31 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]32 %min.idx = phi i64 [ 0, %entry ], [ %min.idx.next, %loop ]33 %min.val = phi i64 [ 0, %entry ], [ %min.val.next, %loop ]34 %gep = getelementptr i64, ptr %src, i64 %iv35 %l = load i64, ptr %gep36 %cmp = icmp ugt i64 %min.val, %l37 %min.val.next = tail call i64 @llvm.umin.i64(i64 %min.val, i64 %l)38 %min.idx.next = select i1 %cmp, i64 %iv, i64 %min.idx39 %iv.next = add nuw nsw i64 %iv, 140 %exitcond.not = icmp eq i64 %iv.next, %n41 br i1 %exitcond.not, label %exit, label %loop42 43exit:44 %res = phi i64 [ %min.idx.next, %loop ]45 ret i64 %res46}47 48define i64 @test_vectorize_select_umin_idx_signed_sentinel_possible(ptr %src, i64 %n) {49; CHECK-LABEL: define i64 @test_vectorize_select_umin_idx_signed_sentinel_possible(50; CHECK-SAME: ptr [[SRC:%.*]], i64 [[N:%.*]]) {51; CHECK-NEXT: [[ENTRY:.*]]:52; CHECK-NEXT: br label %[[LOOP:.*]]53; CHECK: [[LOOP]]:54; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[INDEX_NEXT:%.*]], %[[LOOP]] ]55; CHECK-NEXT: [[MIN_IDX:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[MIN_IDX_NEXT:%.*]], %[[LOOP]] ]56; CHECK-NEXT: [[MIN_VAL:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[MIN_VAL_NEXT:%.*]], %[[LOOP]] ]57; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i64, ptr [[SRC]], i64 [[INDEX]]58; CHECK-NEXT: [[L:%.*]] = load i64, ptr [[TMP0]], align 459; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[MIN_VAL]], [[L]]60; CHECK-NEXT: [[MIN_VAL_NEXT]] = tail call i64 @llvm.umin.i64(i64 [[MIN_VAL]], i64 [[L]])61; CHECK-NEXT: [[MIN_IDX_NEXT]] = select i1 [[CMP]], i64 [[INDEX]], i64 [[MIN_IDX]]62; CHECK-NEXT: [[INDEX_NEXT]] = add nuw nsw i64 [[INDEX]], 163; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i64 [[INDEX_NEXT]], 10064; CHECK-NEXT: br i1 [[TMP4]], label %[[EXIT:.*]], label %[[LOOP]]65; CHECK: [[EXIT]]:66; CHECK-NEXT: [[RDX_SELECT:%.*]] = phi i64 [ [[MIN_IDX_NEXT]], %[[LOOP]] ]67; CHECK-NEXT: ret i64 [[RDX_SELECT]]68;69entry:70 br label %loop71 72loop:73 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]74 %min.idx = phi i64 [ 0, %entry ], [ %min.idx.next, %loop ]75 %min.val = phi i64 [ 0, %entry ], [ %min.val.next, %loop ]76 %gep = getelementptr i64, ptr %src, i64 %iv77 %l = load i64, ptr %gep78 %cmp = icmp ugt i64 %min.val, %l79 %min.val.next = tail call i64 @llvm.umin.i64(i64 %min.val, i64 %l)80 %min.idx.next = select i1 %cmp, i64 %iv, i64 %min.idx81 %iv.next = add nuw nsw i64 %iv, 182 %exitcond.not = icmp eq i64 %iv.next, 10083 br i1 %exitcond.not, label %exit, label %loop84 85exit:86 %res = phi i64 [ %min.idx.next, %loop ]87 ret i64 %res88}89 90define i64 @test_vectorize_select_umin_idx_cond_flipped(ptr %src, i64 %n) {91; CHECK-LABEL: define i64 @test_vectorize_select_umin_idx_cond_flipped(92; CHECK-SAME: ptr [[SRC:%.*]], i64 [[N:%.*]]) {93; CHECK-NEXT: [[ENTRY:.*]]:94; CHECK-NEXT: br label %[[LOOP:.*]]95; CHECK: [[LOOP]]:96; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]97; CHECK-NEXT: [[MIN_IDX:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[MIN_IDX_NEXT:%.*]], %[[LOOP]] ]98; CHECK-NEXT: [[MIN_VAL:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[MIN_VAL_NEXT:%.*]], %[[LOOP]] ]99; CHECK-NEXT: [[GEP:%.*]] = getelementptr i64, ptr [[SRC]], i64 [[IV]]100; CHECK-NEXT: [[L:%.*]] = load i64, ptr [[GEP]], align 4101; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[L]], [[MIN_VAL]]102; CHECK-NEXT: [[MIN_VAL_NEXT]] = tail call i64 @llvm.umin.i64(i64 [[MIN_VAL]], i64 [[L]])103; CHECK-NEXT: [[MIN_IDX_NEXT]] = select i1 [[CMP]], i64 [[IV]], i64 [[MIN_IDX]]104; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1105; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV_NEXT]], [[N]]106; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[EXIT:.*]], label %[[LOOP]]107; CHECK: [[EXIT]]:108; CHECK-NEXT: [[RES:%.*]] = phi i64 [ [[MIN_IDX_NEXT]], %[[LOOP]] ]109; CHECK-NEXT: ret i64 [[RES]]110;111entry:112 br label %loop113 114loop:115 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]116 %min.idx = phi i64 [ 0, %entry ], [ %min.idx.next, %loop ]117 %min.val = phi i64 [ 0, %entry ], [ %min.val.next, %loop ]118 %gep = getelementptr i64, ptr %src, i64 %iv119 %l = load i64, ptr %gep120 %cmp = icmp ult i64 %l, %min.val121 %min.val.next = tail call i64 @llvm.umin.i64(i64 %min.val, i64 %l)122 %min.idx.next = select i1 %cmp, i64 %iv, i64 %min.idx123 %iv.next = add nuw nsw i64 %iv, 1124 %exitcond.not = icmp eq i64 %iv.next, %n125 br i1 %exitcond.not, label %exit, label %loop126 127exit:128 %res = phi i64 [ %min.idx.next, %loop ]129 ret i64 %res130}131 132define i64 @test_vectorize_select_umin_idx_select_ops_flipped(ptr %src, i64 %n) {133; CHECK-LABEL: define i64 @test_vectorize_select_umin_idx_select_ops_flipped(134; CHECK-SAME: ptr [[SRC:%.*]], i64 [[N:%.*]]) {135; CHECK-NEXT: [[ENTRY:.*]]:136; CHECK-NEXT: br label %[[LOOP:.*]]137; CHECK: [[LOOP]]:138; CHECK-NEXT: [[IV1:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]139; CHECK-NEXT: [[MIN_IDX:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[MIN_IDX_NEXT:%.*]], %[[LOOP]] ]140; CHECK-NEXT: [[MIN_VAL:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[MIN_VAL_NEXT:%.*]], %[[LOOP]] ]141; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i64, ptr [[SRC]], i64 [[IV1]]142; CHECK-NEXT: [[L:%.*]] = load i64, ptr [[GEP1]], align 4143; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[L]], [[MIN_VAL]]144; CHECK-NEXT: [[MIN_VAL_NEXT]] = tail call i64 @llvm.umin.i64(i64 [[MIN_VAL]], i64 [[L]])145; CHECK-NEXT: [[MIN_IDX_NEXT]] = select i1 [[CMP]], i64 [[MIN_IDX]], i64 [[IV1]]146; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV1]], 1147; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV_NEXT]], [[N]]148; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[EXIT:.*]], label %[[LOOP]]149; CHECK: [[EXIT]]:150; CHECK-NEXT: [[RES:%.*]] = phi i64 [ [[MIN_IDX_NEXT]], %[[LOOP]] ]151; CHECK-NEXT: ret i64 [[RES]]152;153entry:154 br label %loop155 156loop:157 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]158 %min.idx = phi i64 [ 0, %entry ], [ %min.idx.next, %loop ]159 %min.val = phi i64 [ 0, %entry ], [ %min.val.next, %loop ]160 %gep = getelementptr i64, ptr %src, i64 %iv161 %l = load i64, ptr %gep162 %cmp = icmp ult i64 %l, %min.val163 %min.val.next = tail call i64 @llvm.umin.i64(i64 %min.val, i64 %l)164 %min.idx.next = select i1 %cmp, i64 %min.idx, i64 %iv165 %iv.next = add nuw nsw i64 %iv, 1166 %exitcond.not = icmp eq i64 %iv.next, %n167 br i1 %exitcond.not, label %exit, label %loop168 169exit:170 %res = phi i64 [ %min.idx.next, %loop ]171 ret i64 %res172}173 174define i64 @test_vectorize_select_umin_via_select_idx(ptr %src, i64 %n) {175; CHECK-LABEL: define i64 @test_vectorize_select_umin_via_select_idx(176; CHECK-SAME: ptr [[SRC:%.*]], i64 [[N:%.*]]) {177; CHECK-NEXT: [[ENTRY:.*]]:178; CHECK-NEXT: br label %[[LOOP:.*]]179; CHECK: [[LOOP]]:180; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]181; CHECK-NEXT: [[MIN_IDX:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[MIN_IDX_NEXT:%.*]], %[[LOOP]] ]182; CHECK-NEXT: [[MIN_VAL:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[MIN_VAL_NEXT:%.*]], %[[LOOP]] ]183; CHECK-NEXT: [[GEP:%.*]] = getelementptr i64, ptr [[SRC]], i64 [[IV]]184; CHECK-NEXT: [[L:%.*]] = load i64, ptr [[GEP]], align 4185; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[MIN_VAL]], [[L]]186; CHECK-NEXT: [[MIN_VAL_NEXT]] = select i1 [[CMP]], i64 [[L]], i64 [[MIN_VAL]]187; CHECK-NEXT: [[MIN_IDX_NEXT]] = select i1 [[CMP]], i64 [[IV]], i64 [[MIN_IDX]]188; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1189; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV_NEXT]], [[N]]190; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[EXIT:.*]], label %[[LOOP]]191; CHECK: [[EXIT]]:192; CHECK-NEXT: [[RES:%.*]] = phi i64 [ [[MIN_IDX_NEXT]], %[[LOOP]] ]193; CHECK-NEXT: ret i64 [[RES]]194;195entry:196 br label %loop197 198loop:199 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]200 %min.idx = phi i64 [ 0, %entry ], [ %min.idx.next, %loop ]201 %min.val = phi i64 [ 0, %entry ], [ %min.val.next, %loop ]202 %gep = getelementptr i64, ptr %src, i64 %iv203 %l = load i64, ptr %gep204 %cmp = icmp ugt i64 %min.val, %l205 %min.val.next = select i1 %cmp, i64 %l, i64 %min.val206 %min.idx.next = select i1 %cmp, i64 %iv, i64 %min.idx207 %iv.next = add nuw nsw i64 %iv, 1208 %exitcond.not = icmp eq i64 %iv.next, %n209 br i1 %exitcond.not, label %exit, label %loop210 211exit:212 %res = phi i64 [ %min.idx.next, %loop ]213 ret i64 %res214}215 216define i64 @test_vectorize_select_umin_idx_all_exit_inst(ptr %src, ptr %umin, i64 %n) {217; CHECK-LABEL: define i64 @test_vectorize_select_umin_idx_all_exit_inst(218; CHECK-SAME: ptr [[SRC:%.*]], ptr [[UMIN:%.*]], i64 [[N:%.*]]) {219; CHECK-NEXT: [[ENTRY:.*]]:220; CHECK-NEXT: br label %[[LOOP:.*]]221; CHECK: [[LOOP]]:222; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]223; CHECK-NEXT: [[MIN_IDX:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[MIN_IDX_NEXT:%.*]], %[[LOOP]] ]224; CHECK-NEXT: [[MIN_VAL:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[MIN_VAL_NEXT:%.*]], %[[LOOP]] ]225; CHECK-NEXT: [[GEP:%.*]] = getelementptr i64, ptr [[SRC]], i64 [[IV]]226; CHECK-NEXT: [[L:%.*]] = load i64, ptr [[GEP]], align 4227; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[MIN_VAL]], [[L]]228; CHECK-NEXT: [[MIN_VAL_NEXT]] = tail call i64 @llvm.umin.i64(i64 [[MIN_VAL]], i64 [[L]])229; CHECK-NEXT: [[MIN_IDX_NEXT]] = select i1 [[CMP]], i64 [[IV]], i64 [[MIN_IDX]]230; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1231; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV_NEXT]], [[N]]232; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[EXIT:.*]], label %[[LOOP]]233; CHECK: [[EXIT]]:234; CHECK-NEXT: [[RES:%.*]] = phi i64 [ [[MIN_IDX_NEXT]], %[[LOOP]] ]235; CHECK-NEXT: [[RES_UMIN:%.*]] = phi i64 [ [[MIN_VAL_NEXT]], %[[LOOP]] ]236; CHECK-NEXT: store i64 [[RES_UMIN]], ptr [[UMIN]], align 4237; CHECK-NEXT: ret i64 [[RES]]238;239entry:240 br label %loop241 242loop:243 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]244 %min.idx = phi i64 [ 0, %entry ], [ %min.idx.next, %loop ]245 %min.val = phi i64 [ 0, %entry ], [ %min.val.next, %loop ]246 %gep = getelementptr i64, ptr %src, i64 %iv247 %l = load i64, ptr %gep248 %cmp = icmp ugt i64 %min.val, %l249 %min.val.next = tail call i64 @llvm.umin.i64(i64 %min.val, i64 %l)250 %min.idx.next = select i1 %cmp, i64 %iv, i64 %min.idx251 %iv.next = add nuw nsw i64 %iv, 1252 %exitcond.not = icmp eq i64 %iv.next, %n253 br i1 %exitcond.not, label %exit, label %loop254 255exit:256 %res = phi i64 [ %min.idx.next, %loop ]257 %res.umin = phi i64 [ %min.val.next, %loop ]258 store i64 %res.umin, ptr %umin259 ret i64 %res260}261 262define i64 @test_vectorize_select_umin_idx_min_ops_switched(ptr %src, i64 %n) {263; CHECK-LABEL: define i64 @test_vectorize_select_umin_idx_min_ops_switched(264; CHECK-SAME: ptr [[SRC:%.*]], i64 [[N:%.*]]) {265; CHECK-NEXT: [[ENTRY:.*]]:266; CHECK-NEXT: br label %[[LOOP:.*]]267; CHECK: [[LOOP]]:268; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]269; CHECK-NEXT: [[MIN_IDX:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[MIN_IDX_NEXT:%.*]], %[[LOOP]] ]270; CHECK-NEXT: [[MIN_VAL:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[MIN_VAL_NEXT:%.*]], %[[LOOP]] ]271; CHECK-NEXT: [[GEP:%.*]] = getelementptr i64, ptr [[SRC]], i64 [[IV]]272; CHECK-NEXT: [[L:%.*]] = load i64, ptr [[GEP]], align 4273; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[MIN_VAL]], [[L]]274; CHECK-NEXT: [[MIN_VAL_NEXT]] = tail call i64 @llvm.umin.i64(i64 [[L]], i64 [[MIN_VAL]])275; CHECK-NEXT: [[MIN_IDX_NEXT]] = select i1 [[CMP]], i64 [[IV]], i64 [[MIN_IDX]]276; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1277; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV_NEXT]], [[N]]278; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[EXIT:.*]], label %[[LOOP]]279; CHECK: [[EXIT]]:280; CHECK-NEXT: [[RES:%.*]] = phi i64 [ [[MIN_IDX_NEXT]], %[[LOOP]] ]281; CHECK-NEXT: ret i64 [[RES]]282;283entry:284 br label %loop285 286loop:287 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]288 %min.idx = phi i64 [ 0, %entry ], [ %min.idx.next, %loop ]289 %min.val = phi i64 [ 0, %entry ], [ %min.val.next, %loop ]290 %gep = getelementptr i64, ptr %src, i64 %iv291 %l = load i64, ptr %gep292 %cmp = icmp ugt i64 %min.val, %l293 %min.val.next = tail call i64 @llvm.umin.i64(i64 %l, i64 %min.val)294 %min.idx.next = select i1 %cmp, i64 %iv, i64 %min.idx295 %iv.next = add nuw nsw i64 %iv, 1296 %exitcond.not = icmp eq i64 %iv.next, %n297 br i1 %exitcond.not, label %exit, label %loop298 299exit:300 %res = phi i64 [ %min.idx.next, %loop ]301 ret i64 %res302}303 304define i64 @test_not_vectorize_select_no_min_reduction(ptr %src, i64 %n) {305; CHECK-LABEL: define i64 @test_not_vectorize_select_no_min_reduction(306; CHECK-SAME: ptr [[SRC:%.*]], i64 [[N:%.*]]) {307; CHECK-NEXT: [[ENTRY:.*]]:308; CHECK-NEXT: br label %[[LOOP:.*]]309; CHECK: [[LOOP]]:310; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]311; CHECK-NEXT: [[MIN_IDX:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[MIN_IDX_NEXT:%.*]], %[[LOOP]] ]312; CHECK-NEXT: [[RED_VAL:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[RED_VAL_NEXT:%.*]], %[[LOOP]] ]313; CHECK-NEXT: [[GEP:%.*]] = getelementptr i64, ptr [[SRC]], i64 [[IV]]314; CHECK-NEXT: [[L:%.*]] = load i64, ptr [[GEP]], align 4315; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[RED_VAL]], [[L]]316; CHECK-NEXT: [[RED_VAL_NEXT]] = add i64 [[RED_VAL]], [[L]]317; CHECK-NEXT: [[MIN_IDX_NEXT]] = select i1 [[CMP]], i64 [[IV]], i64 [[MIN_IDX]]318; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1319; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV_NEXT]], [[N]]320; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[EXIT:.*]], label %[[LOOP]]321; CHECK: [[EXIT]]:322; CHECK-NEXT: [[RES:%.*]] = phi i64 [ [[MIN_IDX_NEXT]], %[[LOOP]] ]323; CHECK-NEXT: ret i64 [[RES]]324;325entry:326 br label %loop327 328loop:329 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]330 %min.idx = phi i64 [ 0, %entry ], [ %min.idx.next, %loop ]331 %red.val = phi i64 [ 0, %entry ], [ %red.val.next, %loop ]332 %gep = getelementptr i64, ptr %src, i64 %iv333 %l = load i64, ptr %gep334 %cmp = icmp ugt i64 %red.val, %l335 %red.val.next = add i64 %red.val, %l336 %min.idx.next = select i1 %cmp, i64 %iv, i64 %min.idx337 %iv.next = add nuw nsw i64 %iv, 1338 %exitcond.not = icmp eq i64 %iv.next, %n339 br i1 %exitcond.not, label %exit, label %loop340 341exit:342 %res = phi i64 [ %min.idx.next, %loop ]343 ret i64 %res344}345 346define i64 @test_cmp_and_umin_use_different_values(ptr %src, i64 %x, i64 %n) {347; CHECK-LABEL: define i64 @test_cmp_and_umin_use_different_values(348; CHECK-SAME: ptr [[SRC:%.*]], i64 [[X:%.*]], i64 [[N:%.*]]) {349; CHECK-NEXT: [[ENTRY:.*]]:350; CHECK-NEXT: br label %[[LOOP:.*]]351; CHECK: [[LOOP]]:352; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]353; CHECK-NEXT: [[MIN_IDX:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[MIN_IDX_NEXT:%.*]], %[[LOOP]] ]354; CHECK-NEXT: [[MIN_VAL:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[MIN_VAL_NEXT:%.*]], %[[LOOP]] ]355; CHECK-NEXT: [[GEP:%.*]] = getelementptr i64, ptr [[SRC]], i64 [[IV]]356; CHECK-NEXT: [[L:%.*]] = load i64, ptr [[GEP]], align 4357; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[MIN_VAL]], [[X]]358; CHECK-NEXT: [[MIN_VAL_NEXT]] = tail call i64 @llvm.umin.i64(i64 [[MIN_VAL]], i64 [[L]])359; CHECK-NEXT: [[MIN_IDX_NEXT]] = select i1 [[CMP]], i64 [[IV]], i64 [[MIN_IDX]]360; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1361; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV_NEXT]], [[N]]362; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[EXIT:.*]], label %[[LOOP]]363; CHECK: [[EXIT]]:364; CHECK-NEXT: [[RES:%.*]] = phi i64 [ [[MIN_IDX_NEXT]], %[[LOOP]] ]365; CHECK-NEXT: ret i64 [[RES]]366;367entry:368 br label %loop369 370loop:371 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]372 %min.idx = phi i64 [ 0, %entry ], [ %min.idx.next, %loop ]373 %min.val = phi i64 [ 0, %entry ], [ %min.val.next, %loop ]374 %gep = getelementptr i64, ptr %src, i64 %iv375 %l = load i64, ptr %gep376 %cmp = icmp ugt i64 %min.val, %x377 %min.val.next = tail call i64 @llvm.umin.i64(i64 %min.val, i64 %l)378 %min.idx.next = select i1 %cmp, i64 %iv, i64 %min.idx379 %iv.next = add nuw nsw i64 %iv, 1380 %exitcond.not = icmp eq i64 %iv.next, %n381 br i1 %exitcond.not, label %exit, label %loop382 383exit:384 %res = phi i64 [ %min.idx.next, %loop ]385 ret i64 %res386}387 388define i32 @test_vectorize_select_umin_idx_with_trunc(ptr %src, i64 %n) {389; CHECK-LABEL: define i32 @test_vectorize_select_umin_idx_with_trunc(390; CHECK-SAME: ptr [[SRC:%.*]], i64 [[N:%.*]]) {391; CHECK-NEXT: [[ENTRY:.*]]:392; CHECK-NEXT: br label %[[LOOP:.*]]393; CHECK: [[LOOP]]:394; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]395; CHECK-NEXT: [[MIN_IDX:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[MIN_IDX_NEXT:%.*]], %[[LOOP]] ]396; CHECK-NEXT: [[MIN_VAL:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[MIN_VAL_NEXT:%.*]], %[[LOOP]] ]397; CHECK-NEXT: [[GEP:%.*]] = getelementptr i64, ptr [[SRC]], i64 [[IV]]398; CHECK-NEXT: [[L:%.*]] = load i64, ptr [[GEP]], align 4399; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[MIN_VAL]], [[L]]400; CHECK-NEXT: [[MIN_VAL_NEXT]] = tail call i64 @llvm.umin.i64(i64 [[MIN_VAL]], i64 [[L]])401; CHECK-NEXT: [[TRUNC:%.*]] = trunc i64 [[IV]] to i32402; CHECK-NEXT: [[MIN_IDX_NEXT]] = select i1 [[CMP]], i32 [[TRUNC]], i32 [[MIN_IDX]]403; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1404; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV_NEXT]], [[N]]405; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[EXIT:.*]], label %[[LOOP]]406; CHECK: [[EXIT]]:407; CHECK-NEXT: [[RES:%.*]] = phi i32 [ [[MIN_IDX_NEXT]], %[[LOOP]] ]408; CHECK-NEXT: ret i32 [[RES]]409;410entry:411 br label %loop412 413loop:414 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]415 %min.idx = phi i32 [ 0, %entry ], [ %min.idx.next, %loop ]416 %min.val = phi i64 [ 0, %entry ], [ %min.val.next, %loop ]417 %gep = getelementptr i64, ptr %src, i64 %iv418 %l = load i64, ptr %gep419 %cmp = icmp ugt i64 %min.val, %l420 %min.val.next = tail call i64 @llvm.umin.i64(i64 %min.val, i64 %l)421 %trunc = trunc i64 %iv to i32422 %min.idx.next = select i1 %cmp, i32 %trunc, i32 %min.idx423 %iv.next = add nuw nsw i64 %iv, 1424 %exitcond.not = icmp eq i64 %iv.next, %n425 br i1 %exitcond.not, label %exit, label %loop426 427exit:428 %res = phi i32 [ %min.idx.next, %loop ]429 ret i32 %res430}431 432define ptr @test_with_ptr_index(ptr %start, ptr %end) {433; CHECK-LABEL: define ptr @test_with_ptr_index(434; CHECK-SAME: ptr [[START:%.*]], ptr [[END:%.*]]) {435; CHECK-NEXT: [[ENTRY:.*]]:436; CHECK-NEXT: br label %[[LOOP:.*]]437; CHECK: [[LOOP]]:438; CHECK-NEXT: [[IV:%.*]] = phi ptr [ [[START]], %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]439; CHECK-NEXT: [[MIN_IDX:%.*]] = phi ptr [ null, %[[ENTRY]] ], [ [[MIN_IDX_NEXT:%.*]], %[[LOOP]] ]440; CHECK-NEXT: [[MIN_VAL:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[MIN_VAL_NEXT:%.*]], %[[LOOP]] ]441; CHECK-NEXT: [[L:%.*]] = load i64, ptr [[IV]], align 4442; CHECK-NEXT: [[CMP7_US:%.*]] = icmp ult i64 [[L]], [[MIN_VAL]]443; CHECK-NEXT: [[MIN_VAL_NEXT]] = tail call i64 @llvm.umin.i64(i64 [[MIN_VAL]], i64 [[L]])444; CHECK-NEXT: [[MIN_IDX_NEXT]] = select i1 [[CMP7_US]], ptr [[IV]], ptr [[MIN_IDX]]445; CHECK-NEXT: [[IV_NEXT]] = getelementptr i32, ptr [[IV]], i64 1446; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq ptr [[IV_NEXT]], [[END]]447; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[EXIT:.*]], label %[[LOOP]]448; CHECK: [[EXIT]]:449; CHECK-NEXT: [[RES:%.*]] = phi ptr [ [[MIN_IDX_NEXT]], %[[LOOP]] ]450; CHECK-NEXT: ret ptr [[RES]]451;452entry:453 br label %loop454 455loop:456 %iv = phi ptr [ %start, %entry ], [ %iv.next, %loop ]457 %min.idx = phi ptr [ null, %entry ], [ %min.idx.next, %loop ]458 %min.val = phi i64 [ 0, %entry ], [ %min.val.next, %loop ]459 %l = load i64, ptr %iv460 %cmp7.us = icmp ult i64 %l, %min.val461 %min.val.next = tail call i64 @llvm.umin.i64(i64 %min.val, i64 %l)462 %min.idx.next = select i1 %cmp7.us, ptr %iv, ptr %min.idx463 %iv.next = getelementptr i32, ptr %iv, i64 1464 %exitcond.not = icmp eq ptr %iv.next, %end465 br i1 %exitcond.not, label %exit, label %loop466 467exit:468 %res = phi ptr [ %min.idx.next, %loop ]469 ret ptr %res470}471 472define i64 @test_no_vectorize_select_iv_decrement(ptr %src) {473; CHECK-LABEL: define i64 @test_no_vectorize_select_iv_decrement(474; CHECK-SAME: ptr [[SRC:%.*]]) {475; CHECK-NEXT: [[ENTRY:.*]]:476; CHECK-NEXT: br label %[[LOOP:.*]]477; CHECK: [[LOOP]]:478; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 1000, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]479; CHECK-NEXT: [[MIN_IDX:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[MIN_IDX_NEXT:%.*]], %[[LOOP]] ]480; CHECK-NEXT: [[MIN_VAL:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[MIN_VAL_NEXT:%.*]], %[[LOOP]] ]481; CHECK-NEXT: [[GEP:%.*]] = getelementptr i64, ptr [[SRC]], i64 [[IV]]482; CHECK-NEXT: [[L:%.*]] = load i64, ptr [[GEP]], align 4483; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[MIN_VAL]], [[L]]484; CHECK-NEXT: [[MIN_VAL_NEXT]] = tail call i64 @llvm.umin.i64(i64 [[MIN_VAL]], i64 [[L]])485; CHECK-NEXT: [[MIN_IDX_NEXT]] = select i1 [[CMP]], i64 [[IV]], i64 [[MIN_IDX]]486; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], -1487; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV_NEXT]], 0488; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[EXIT:.*]], label %[[LOOP]]489; CHECK: [[EXIT]]:490; CHECK-NEXT: [[RES:%.*]] = phi i64 [ [[MIN_IDX_NEXT]], %[[LOOP]] ]491; CHECK-NEXT: ret i64 [[RES]]492;493entry:494 br label %loop495 496loop:497 %iv = phi i64 [ 1000, %entry ], [ %iv.next, %loop ]498 %min.idx = phi i64 [ 0, %entry ], [ %min.idx.next, %loop ]499 %min.val = phi i64 [ 0, %entry ], [ %min.val.next, %loop ]500 %gep = getelementptr i64, ptr %src, i64 %iv501 %l = load i64, ptr %gep502 %cmp = icmp ugt i64 %min.val, %l503 %min.val.next = tail call i64 @llvm.umin.i64(i64 %min.val, i64 %l)504 %min.idx.next = select i1 %cmp, i64 %iv, i64 %min.idx505 %iv.next = add nuw nsw i64 %iv, -1506 %exitcond.not = icmp eq i64 %iv.next, 0507 br i1 %exitcond.not, label %exit, label %loop508 509exit:510 %res = phi i64 [ %min.idx.next, %loop ]511 ret i64 %res512}513 514define i64 @test_no_vectorize_select_iv_sub(ptr %src) {515; CHECK-LABEL: define i64 @test_no_vectorize_select_iv_sub(516; CHECK-SAME: ptr [[SRC:%.*]]) {517; CHECK-NEXT: [[ENTRY:.*]]:518; CHECK-NEXT: br label %[[LOOP:.*]]519; CHECK: [[LOOP]]:520; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 1000, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]521; CHECK-NEXT: [[MIN_IDX:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[MIN_IDX_NEXT:%.*]], %[[LOOP]] ]522; CHECK-NEXT: [[MIN_VAL:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[MIN_VAL_NEXT:%.*]], %[[LOOP]] ]523; CHECK-NEXT: [[GEP:%.*]] = getelementptr i64, ptr [[SRC]], i64 [[IV]]524; CHECK-NEXT: [[L:%.*]] = load i64, ptr [[GEP]], align 4525; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[MIN_VAL]], [[L]]526; CHECK-NEXT: [[MIN_VAL_NEXT]] = tail call i64 @llvm.umin.i64(i64 [[MIN_VAL]], i64 [[L]])527; CHECK-NEXT: [[MIN_IDX_NEXT]] = select i1 [[CMP]], i64 [[IV]], i64 [[MIN_IDX]]528; CHECK-NEXT: [[IV_NEXT]] = sub i64 [[IV]], 1529; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV_NEXT]], 0530; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[EXIT:.*]], label %[[LOOP]]531; CHECK: [[EXIT]]:532; CHECK-NEXT: [[RES:%.*]] = phi i64 [ [[MIN_IDX_NEXT]], %[[LOOP]] ]533; CHECK-NEXT: ret i64 [[RES]]534;535entry:536 br label %loop537 538loop:539 %iv = phi i64 [ 1000, %entry ], [ %iv.next, %loop ]540 %min.idx = phi i64 [ 0, %entry ], [ %min.idx.next, %loop ]541 %min.val = phi i64 [ 0, %entry ], [ %min.val.next, %loop ]542 %gep = getelementptr i64, ptr %src, i64 %iv543 %l = load i64, ptr %gep544 %cmp = icmp ugt i64 %min.val, %l545 %min.val.next = tail call i64 @llvm.umin.i64(i64 %min.val, i64 %l)546 %min.idx.next = select i1 %cmp, i64 %iv, i64 %min.idx547 %iv.next = sub i64 %iv, 1548 %exitcond.not = icmp eq i64 %iv.next, 0549 br i1 %exitcond.not, label %exit, label %loop550 551exit:552 %res = phi i64 [ %min.idx.next, %loop ]553 ret i64 %res554}555 556define i64 @test_no_vectorize_select_iv_mul(ptr %src) {557; CHECK-LABEL: define i64 @test_no_vectorize_select_iv_mul(558; CHECK-SAME: ptr [[SRC:%.*]]) {559; CHECK-NEXT: [[ENTRY:.*]]:560; CHECK-NEXT: br label %[[LOOP:.*]]561; CHECK: [[LOOP]]:562; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 1, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]563; CHECK-NEXT: [[MIN_IDX:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[MIN_IDX_NEXT:%.*]], %[[LOOP]] ]564; CHECK-NEXT: [[MIN_VAL:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[MIN_VAL_NEXT:%.*]], %[[LOOP]] ]565; CHECK-NEXT: [[GEP:%.*]] = getelementptr i64, ptr [[SRC]], i64 [[IV]]566; CHECK-NEXT: [[L:%.*]] = load i64, ptr [[GEP]], align 4567; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[MIN_VAL]], [[L]]568; CHECK-NEXT: [[MIN_VAL_NEXT]] = tail call i64 @llvm.umin.i64(i64 [[MIN_VAL]], i64 [[L]])569; CHECK-NEXT: [[MIN_IDX_NEXT]] = select i1 [[CMP]], i64 [[IV]], i64 [[MIN_IDX]]570; CHECK-NEXT: [[IV_NEXT]] = mul i64 [[IV]], 2571; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV_NEXT]], 128572; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[EXIT:.*]], label %[[LOOP]]573; CHECK: [[EXIT]]:574; CHECK-NEXT: [[RES:%.*]] = phi i64 [ [[MIN_IDX_NEXT]], %[[LOOP]] ]575; CHECK-NEXT: ret i64 [[RES]]576;577entry:578 br label %loop579 580loop:581 %iv = phi i64 [ 1, %entry ], [ %iv.next, %loop ]582 %min.idx = phi i64 [ 0, %entry ], [ %min.idx.next, %loop ]583 %min.val = phi i64 [ 0, %entry ], [ %min.val.next, %loop ]584 %gep = getelementptr i64, ptr %src, i64 %iv585 %l = load i64, ptr %gep586 %cmp = icmp ugt i64 %min.val, %l587 %min.val.next = tail call i64 @llvm.umin.i64(i64 %min.val, i64 %l)588 %min.idx.next = select i1 %cmp, i64 %iv, i64 %min.idx589 %iv.next = mul i64 %iv, 2590 %exitcond.not = icmp eq i64 %iv.next, 128591 br i1 %exitcond.not, label %exit, label %loop592 593exit:594 %res = phi i64 [ %min.idx.next, %loop ]595 ret i64 %res596}597 598define i64 @test_vectorize_select_umin_idx_wraps(ptr %src, i64 %n, i64 %start) {599; CHECK-LABEL: define i64 @test_vectorize_select_umin_idx_wraps(600; CHECK-SAME: ptr [[SRC:%.*]], i64 [[N:%.*]], i64 [[START:%.*]]) {601; CHECK-NEXT: [[ENTRY:.*]]:602; CHECK-NEXT: br label %[[LOOP:.*]]603; CHECK: [[LOOP]]:604; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]605; CHECK-NEXT: [[IDX:%.*]] = phi i64 [ [[START]], %[[ENTRY]] ], [ [[IDX_NEXT:%.*]], %[[LOOP]] ]606; CHECK-NEXT: [[MIN_IDX:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[MIN_IDX_NEXT:%.*]], %[[LOOP]] ]607; CHECK-NEXT: [[MIN_VAL:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[MIN_VAL_NEXT:%.*]], %[[LOOP]] ]608; CHECK-NEXT: [[GEP:%.*]] = getelementptr i64, ptr [[SRC]], i64 [[IV]]609; CHECK-NEXT: [[L:%.*]] = load i64, ptr [[GEP]], align 4610; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[MIN_VAL]], [[L]]611; CHECK-NEXT: [[MIN_VAL_NEXT]] = tail call i64 @llvm.umin.i64(i64 [[MIN_VAL]], i64 [[L]])612; CHECK-NEXT: [[MIN_IDX_NEXT]] = select i1 [[CMP]], i64 [[IDX]], i64 [[MIN_IDX]]613; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1614; CHECK-NEXT: [[IDX_NEXT]] = add i64 [[IDX]], 1615; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV_NEXT]], [[N]]616; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[EXIT:.*]], label %[[LOOP]]617; CHECK: [[EXIT]]:618; CHECK-NEXT: [[RES:%.*]] = phi i64 [ [[MIN_IDX_NEXT]], %[[LOOP]] ]619; CHECK-NEXT: ret i64 [[RES]]620;621entry:622 br label %loop623 624loop:625 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]626 %idx = phi i64 [ %start, %entry ], [ %idx.next, %loop ]627 %min.idx = phi i64 [ 0, %entry ], [ %min.idx.next, %loop ]628 %min.val = phi i64 [ 0, %entry ], [ %min.val.next, %loop ]629 %gep = getelementptr i64, ptr %src, i64 %iv630 %l = load i64, ptr %gep631 %cmp = icmp ugt i64 %min.val, %l632 %min.val.next = tail call i64 @llvm.umin.i64(i64 %min.val, i64 %l)633 %min.idx.next = select i1 %cmp, i64 %idx, i64 %min.idx634 %iv.next = add nuw nsw i64 %iv, 1635 %idx.next = add i64 %idx, 1636 %exitcond.not = icmp eq i64 %iv.next, %n637 br i1 %exitcond.not, label %exit, label %loop638 639exit:640 %res = phi i64 [ %min.idx.next, %loop ]641 ret i64 %res642}643 644 645declare i64 @llvm.umin.i64(i64, i64)646declare i16 @llvm.umin.i16(i16, i16)647