257 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 22; RUN: opt < %s -passes=loop-vectorize,dce,instcombine -force-vector-interleave=1 -force-vector-width=4 -prefer-inloop-reductions -S | FileCheck %s3 4define i32 @reduction_smin(ptr nocapture %A, ptr nocapture %B) {5; CHECK-LABEL: define i32 @reduction_smin6; CHECK-SAME: (ptr captures(none) [[A:%.*]], ptr captures(none) [[B:%.*]]) {7; CHECK-NEXT: entry:8; CHECK-NEXT: br label [[VECTOR_PH:%.*]]9; CHECK: vector.ph:10; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]11; CHECK: vector.body:12; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]13; CHECK-NEXT: [[VEC_PHI:%.*]] = phi i32 [ 1000, [[VECTOR_PH]] ], [ [[RDX_MINMAX:%.*]], [[VECTOR_BODY]] ]14; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[INDEX]]15; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, ptr [[TMP0]], align 416; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.vector.reduce.smin.v4i32(<4 x i32> [[WIDE_LOAD]])17; CHECK-NEXT: [[RDX_MINMAX]] = call i32 @llvm.smin.i32(i32 [[TMP1]], i32 [[VEC_PHI]])18; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 419; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[INDEX_NEXT]], 25620; CHECK-NEXT: br i1 [[TMP2]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]]21; CHECK: middle.block:22; CHECK-NEXT: br label [[FOR_END:%.*]]23; CHECK: for.end:24; CHECK-NEXT: ret i32 [[RDX_MINMAX]]25;26entry:27 br label %for.body28 29for.body: ; preds = %entry, %for.body30 %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ]31 %result.08 = phi i32 [ %v0, %for.body ], [ 1000, %entry ]32 %arrayidx = getelementptr inbounds i32, ptr %A, i64 %indvars.iv33 %l0 = load i32, ptr %arrayidx, align 434 %c0 = icmp slt i32 %result.08, %l035 %v0 = select i1 %c0, i32 %result.08, i32 %l036 %indvars.iv.next = add i64 %indvars.iv, 137 %lftr.wideiv = trunc i64 %indvars.iv.next to i3238 %exitcond = icmp eq i32 %lftr.wideiv, 25639 br i1 %exitcond, label %for.end, label %for.body40 41for.end: ; preds = %for.body, %entry42 %result.0.lcssa = phi i32 [ %v0, %for.body ]43 ret i32 %result.0.lcssa44}45 46define i32 @reduction_smin_select_ops_flipped(ptr nocapture %A, ptr nocapture %B) {47; CHECK-LABEL: define i32 @reduction_smin_select_ops_flipped48; CHECK-SAME: (ptr captures(none) [[A:%.*]], ptr captures(none) [[B:%.*]]) {49; CHECK-NEXT: entry:50; CHECK-NEXT: br label [[VECTOR_PH:%.*]]51; CHECK: vector.ph:52; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]53; CHECK: vector.body:54; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]55; CHECK-NEXT: [[VEC_PHI:%.*]] = phi i32 [ 1000, [[VECTOR_PH]] ], [ [[RDX_MINMAX:%.*]], [[VECTOR_BODY]] ]56; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[INDEX]]57; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, ptr [[TMP0]], align 458; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.vector.reduce.smax.v4i32(<4 x i32> [[WIDE_LOAD]])59; CHECK-NEXT: [[RDX_MINMAX]] = call i32 @llvm.smax.i32(i32 [[TMP1]], i32 [[VEC_PHI]])60; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 461; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[INDEX_NEXT]], 25662; CHECK-NEXT: br i1 [[TMP2]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP3:![0-9]+]]63; CHECK: middle.block:64; CHECK-NEXT: br label [[FOR_END:%.*]]65; CHECK: for.end:66; CHECK-NEXT: ret i32 [[RDX_MINMAX]]67;68entry:69 br label %for.body70 71for.body: ; preds = %entry, %for.body72 %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ]73 %result.08 = phi i32 [ %v0, %for.body ], [ 1000, %entry ]74 %arrayidx = getelementptr inbounds i32, ptr %A, i64 %indvars.iv75 %l0 = load i32, ptr %arrayidx, align 476 %c0 = icmp slt i32 %result.08, %l077 %v0 = select i1 %c0, i32 %l0, i32 %result.0878 %indvars.iv.next = add i64 %indvars.iv, 179 %lftr.wideiv = trunc i64 %indvars.iv.next to i3280 %exitcond = icmp eq i32 %lftr.wideiv, 25681 br i1 %exitcond, label %for.end, label %for.body82 83for.end: ; preds = %for.body, %entry84 %result.0.lcssa = phi i32 [ %v0, %for.body ]85 ret i32 %result.0.lcssa86}87 88define i32 @reduction_smin_intrinsic(ptr nocapture %A, ptr nocapture %B) {89; CHECK-LABEL: define i32 @reduction_smin_intrinsic90; CHECK-SAME: (ptr captures(none) [[A:%.*]], ptr captures(none) [[B:%.*]]) {91; CHECK-NEXT: entry:92; CHECK-NEXT: br label [[VECTOR_PH:%.*]]93; CHECK: vector.ph:94; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]95; CHECK: vector.body:96; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]97; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ splat (i32 1000), [[VECTOR_PH]] ], [ [[TMP1:%.*]], [[VECTOR_BODY]] ]98; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[INDEX]]99; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, ptr [[TMP0]], align 4100; CHECK-NEXT: [[TMP1]] = call <4 x i32> @llvm.smin.v4i32(<4 x i32> [[VEC_PHI]], <4 x i32> [[WIDE_LOAD]])101; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4102; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[INDEX_NEXT]], 256103; CHECK-NEXT: br i1 [[TMP2]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]]104; CHECK: middle.block:105; CHECK-NEXT: br label [[FOR_END:%.*]]106; CHECK: for.end:107; CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.vector.reduce.smin.v4i32(<4 x i32> [[TMP1]])108; CHECK-NEXT: ret i32 [[TMP3]]109;110entry:111 br label %for.body112 113for.body: ; preds = %entry, %for.body114 %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ]115 %result.08 = phi i32 [ %v0, %for.body ], [ 1000, %entry ]116 %arrayidx = getelementptr inbounds i32, ptr %A, i64 %indvars.iv117 %l0 = load i32, ptr %arrayidx, align 4118 %v0 = call i32 @llvm.smin.i32(i32 %result.08, i32 %l0)119 %indvars.iv.next = add i64 %indvars.iv, 1120 %lftr.wideiv = trunc i64 %indvars.iv.next to i32121 %exitcond = icmp eq i32 %lftr.wideiv, 256122 br i1 %exitcond, label %for.end, label %for.body123 124for.end: ; preds = %for.body, %entry125 %result.0.lcssa = phi i32 [ %v0, %for.body ]126 ret i32 %result.0.lcssa127}128 129declare i32 @llvm.smin.i32(i32, i32)130 131define i32 @reduction_umax(ptr nocapture %A, ptr nocapture %B) {132; CHECK-LABEL: define i32 @reduction_umax133; CHECK-SAME: (ptr captures(none) [[A:%.*]], ptr captures(none) [[B:%.*]]) {134; CHECK-NEXT: entry:135; CHECK-NEXT: br label [[VECTOR_PH:%.*]]136; CHECK: vector.ph:137; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]138; CHECK: vector.body:139; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]140; CHECK-NEXT: [[VEC_PHI:%.*]] = phi i32 [ 1000, [[VECTOR_PH]] ], [ [[RDX_MINMAX:%.*]], [[VECTOR_BODY]] ]141; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[INDEX]]142; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, ptr [[TMP0]], align 4143; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.vector.reduce.umax.v4i32(<4 x i32> [[WIDE_LOAD]])144; CHECK-NEXT: [[RDX_MINMAX]] = call i32 @llvm.umax.i32(i32 [[TMP1]], i32 [[VEC_PHI]])145; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4146; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[INDEX_NEXT]], 256147; CHECK-NEXT: br i1 [[TMP2]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP5:![0-9]+]]148; CHECK: middle.block:149; CHECK-NEXT: br label [[FOR_END:%.*]]150; CHECK: for.end:151; CHECK-NEXT: ret i32 [[RDX_MINMAX]]152;153entry:154 br label %for.body155 156for.body: ; preds = %entry, %for.body157 %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ]158 %result.08 = phi i32 [ %v0, %for.body ], [ 1000, %entry ]159 %arrayidx = getelementptr inbounds i32, ptr %A, i64 %indvars.iv160 %l0 = load i32, ptr %arrayidx, align 4161 %c0 = icmp ugt i32 %result.08, %l0162 %v0 = select i1 %c0, i32 %result.08, i32 %l0163 %indvars.iv.next = add i64 %indvars.iv, 1164 %lftr.wideiv = trunc i64 %indvars.iv.next to i32165 %exitcond = icmp eq i32 %lftr.wideiv, 256166 br i1 %exitcond, label %for.end, label %for.body167 168for.end: ; preds = %for.body, %entry169 %result.0.lcssa = phi i32 [ %v0, %for.body ]170 ret i32 %result.0.lcssa171}172 173define i32 @reduction_umax_select_ops_flipped(ptr nocapture %A, ptr nocapture %B) {174; CHECK-LABEL: define i32 @reduction_umax_select_ops_flipped175; CHECK-SAME: (ptr captures(none) [[A:%.*]], ptr captures(none) [[B:%.*]]) {176; CHECK-NEXT: entry:177; CHECK-NEXT: br label [[VECTOR_PH:%.*]]178; CHECK: vector.ph:179; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]180; CHECK: vector.body:181; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]182; CHECK-NEXT: [[VEC_PHI:%.*]] = phi i32 [ 1000, [[VECTOR_PH]] ], [ [[RDX_MINMAX:%.*]], [[VECTOR_BODY]] ]183; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[INDEX]]184; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, ptr [[TMP0]], align 4185; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.vector.reduce.umin.v4i32(<4 x i32> [[WIDE_LOAD]])186; CHECK-NEXT: [[RDX_MINMAX]] = call i32 @llvm.umin.i32(i32 [[TMP1]], i32 [[VEC_PHI]])187; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4188; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[INDEX_NEXT]], 256189; CHECK-NEXT: br i1 [[TMP2]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP6:![0-9]+]]190; CHECK: middle.block:191; CHECK-NEXT: br label [[FOR_END:%.*]]192; CHECK: for.end:193; CHECK-NEXT: ret i32 [[RDX_MINMAX]]194;195entry:196 br label %for.body197 198for.body: ; preds = %entry, %for.body199 %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ]200 %result.08 = phi i32 [ %v0, %for.body ], [ 1000, %entry ]201 %arrayidx = getelementptr inbounds i32, ptr %A, i64 %indvars.iv202 %l0 = load i32, ptr %arrayidx, align 4203 %c0 = icmp ugt i32 %result.08, %l0204 %v0 = select i1 %c0, i32 %l0, i32 %result.08205 %indvars.iv.next = add i64 %indvars.iv, 1206 %lftr.wideiv = trunc i64 %indvars.iv.next to i32207 %exitcond = icmp eq i32 %lftr.wideiv, 256208 br i1 %exitcond, label %for.end, label %for.body209 210for.end: ; preds = %for.body, %entry211 %result.0.lcssa = phi i32 [ %v0, %for.body ]212 ret i32 %result.0.lcssa213}214 215define i32 @reduction_umax_intrinsic(ptr nocapture %A, ptr nocapture %B) {216; CHECK-LABEL: define i32 @reduction_umax_intrinsic217; CHECK-SAME: (ptr captures(none) [[A:%.*]], ptr captures(none) [[B:%.*]]) {218; CHECK-NEXT: entry:219; CHECK-NEXT: br label [[VECTOR_PH:%.*]]220; CHECK: vector.ph:221; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]222; CHECK: vector.body:223; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]224; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ splat (i32 1000), [[VECTOR_PH]] ], [ [[TMP1:%.*]], [[VECTOR_BODY]] ]225; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[INDEX]]226; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, ptr [[TMP0]], align 4227; CHECK-NEXT: [[TMP1]] = call <4 x i32> @llvm.umax.v4i32(<4 x i32> [[VEC_PHI]], <4 x i32> [[WIDE_LOAD]])228; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4229; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[INDEX_NEXT]], 256230; CHECK-NEXT: br i1 [[TMP2]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP7:![0-9]+]]231; CHECK: middle.block:232; CHECK-NEXT: br label [[FOR_END:%.*]]233; CHECK: for.end:234; CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.vector.reduce.umax.v4i32(<4 x i32> [[TMP1]])235; CHECK-NEXT: ret i32 [[TMP3]]236;237entry:238 br label %for.body239 240for.body: ; preds = %entry, %for.body241 %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ]242 %result.08 = phi i32 [ %v0, %for.body ], [ 1000, %entry ]243 %arrayidx = getelementptr inbounds i32, ptr %A, i64 %indvars.iv244 %l0 = load i32, ptr %arrayidx, align 4245 %v0 = call i32 @llvm.umax.i32(i32 %result.08, i32 %l0)246 %indvars.iv.next = add i64 %indvars.iv, 1247 %lftr.wideiv = trunc i64 %indvars.iv.next to i32248 %exitcond = icmp eq i32 %lftr.wideiv, 256249 br i1 %exitcond, label %for.end, label %for.body250 251for.end: ; preds = %for.body, %entry252 %result.0.lcssa = phi i32 [ %v0, %for.body ]253 ret i32 %result.0.lcssa254}255 256declare i32 @llvm.umax.i32(i32, i32)257