406 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -passes=instcombine -S < %s | FileCheck %s3 4declare void @use(i32)5declare void @usef32(float)6 7declare i32 @llvm.ctlz.i32(i32, i1)8declare <3 x i17> @llvm.ctlz.v3i17(<3 x i17>, i1)9 10declare i32 @llvm.cttz.i32(i32, i1)11declare <3 x i5> @llvm.cttz.v3i5(<3 x i5>, i1)12 13declare i32 @llvm.ctpop.i32(i32)14declare <3 x i7> @llvm.ctpop.v3i7(<3 x i7>)15 16declare i32 @llvm.usub.sat.i32(i32, i32)17 18define i32 @ctlz_sel_const_true_false(i1 %b) {19; CHECK-LABEL: @ctlz_sel_const_true_false(20; CHECK-NEXT: [[C:%.*]] = select i1 [[B:%.*]], i32 29, i32 021; CHECK-NEXT: ret i32 [[C]]22;23 %s = select i1 %b, i32 5, i32 -724 %c = call i32 @llvm.ctlz.i32(i32 %s, i1 true)25 ret i32 %c26}27 28define i32 @ctlz_sel_const_true(i1 %b, i32 %x) {29; CHECK-LABEL: @ctlz_sel_const_true(30; CHECK-NEXT: [[TMP1:%.*]] = call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 [[X:%.*]], i1 false)31; CHECK-NEXT: [[C:%.*]] = select i1 [[B:%.*]], i32 29, i32 [[TMP1]]32; CHECK-NEXT: ret i32 [[C]]33;34 %s = select i1 %b, i32 5, i32 %x35 %c = call i32 @llvm.ctlz.i32(i32 %s, i1 false)36 ret i32 %c37}38 39define <3 x i17> @ctlz_sel_const_false(<3 x i1> %b, <3 x i17> %x) {40; CHECK-LABEL: @ctlz_sel_const_false(41; CHECK-NEXT: [[TMP1:%.*]] = call range(i17 0, 18) <3 x i17> @llvm.ctlz.v3i17(<3 x i17> [[X:%.*]], i1 true)42; CHECK-NEXT: [[C:%.*]] = select <3 x i1> [[B:%.*]], <3 x i17> [[TMP1]], <3 x i17> <i17 14, i17 0, i17 poison>43; CHECK-NEXT: ret <3 x i17> [[C]]44;45 %s = select <3 x i1> %b, <3 x i17> %x, <3 x i17> <i17 7, i17 -1, i17 0>46 %c = call <3 x i17> @llvm.ctlz.v3i17(<3 x i17> %s, i1 true)47 ret <3 x i17> %c48}49 50define i32 @ctlz_sel_const_true_false_extra_use(i1 %b) {51; CHECK-LABEL: @ctlz_sel_const_true_false_extra_use(52; CHECK-NEXT: [[S:%.*]] = select i1 [[B:%.*]], i32 -1, i32 753; CHECK-NEXT: call void @use(i32 [[S]])54; CHECK-NEXT: [[C:%.*]] = call range(i32 0, 30) i32 @llvm.ctlz.i32(i32 [[S]], i1 true)55; CHECK-NEXT: ret i32 [[C]]56;57 %s = select i1 %b, i32 -1, i32 758 call void @use(i32 %s)59 %c = call i32 @llvm.ctlz.i32(i32 %s, i1 false)60 ret i32 %c61}62 63define i32 @cttz_sel_const_true_false(i1 %b) {64; CHECK-LABEL: @cttz_sel_const_true_false(65; CHECK-NEXT: [[C:%.*]] = select i1 [[B:%.*]], i32 2, i32 066; CHECK-NEXT: ret i32 [[C]]67;68 %s = select i1 %b, i32 4, i32 -769 %c = call i32 @llvm.cttz.i32(i32 %s, i1 false)70 ret i32 %c71}72 73define i32 @cttz_sel_const_true(i1 %b, i32 %x) {74; CHECK-LABEL: @cttz_sel_const_true(75; CHECK-NEXT: [[TMP1:%.*]] = call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 true)76; CHECK-NEXT: [[C:%.*]] = select i1 [[B:%.*]], i32 0, i32 [[TMP1]]77; CHECK-NEXT: ret i32 [[C]]78;79 %s = select i1 %b, i32 5, i32 %x80 %c = call i32 @llvm.cttz.i32(i32 %s, i1 true)81 ret i32 %c82}83 84define <3 x i5> @cttz_sel_const_false(<3 x i1> %b, <3 x i5> %x) {85; CHECK-LABEL: @cttz_sel_const_false(86; CHECK-NEXT: [[TMP1:%.*]] = call range(i5 0, 6) <3 x i5> @llvm.cttz.v3i5(<3 x i5> [[X:%.*]], i1 false)87; CHECK-NEXT: [[C:%.*]] = select <3 x i1> [[B:%.*]], <3 x i5> [[TMP1]], <3 x i5> <i5 0, i5 0, i5 5>88; CHECK-NEXT: ret <3 x i5> [[C]]89;90 %s = select <3 x i1> %b, <3 x i5> %x, <3 x i5> <i5 7, i5 -1, i5 0>91 %c = call <3 x i5> @llvm.cttz.v3i5(<3 x i5> %s, i1 false)92 ret <3 x i5> %c93}94 95define i32 @cttz_sel_const_true_false_extra_use(i1 %b) {96; CHECK-LABEL: @cttz_sel_const_true_false_extra_use(97; CHECK-NEXT: [[S:%.*]] = select i1 [[B:%.*]], i32 5, i32 -898; CHECK-NEXT: call void @use(i32 [[S]])99; CHECK-NEXT: [[C:%.*]] = call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[S]], i1 true)100; CHECK-NEXT: ret i32 [[C]]101;102 %s = select i1 %b, i32 5, i32 -8103 call void @use(i32 %s)104 %c = call i32 @llvm.cttz.i32(i32 %s, i1 true)105 ret i32 %c106}107 108define i32 @ctpop_sel_const_true_false(i1 %b) {109; CHECK-LABEL: @ctpop_sel_const_true_false(110; CHECK-NEXT: [[C:%.*]] = select i1 [[B:%.*]], i32 2, i32 30111; CHECK-NEXT: ret i32 [[C]]112;113 %s = select i1 %b, i32 5, i32 -7114 %c = call i32 @llvm.ctpop.i32(i32 %s)115 ret i32 %c116}117 118define i32 @ctpop_sel_const_true(i1 %b, i32 %x) {119; CHECK-LABEL: @ctpop_sel_const_true(120; CHECK-NEXT: [[TMP1:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])121; CHECK-NEXT: [[C:%.*]] = select i1 [[B:%.*]], i32 2, i32 [[TMP1]]122; CHECK-NEXT: ret i32 [[C]]123;124 %s = select i1 %b, i32 5, i32 %x125 %c = call i32 @llvm.ctpop.i32(i32 %s)126 ret i32 %c127}128 129define <3 x i7> @ctpop_sel_const_false(<3 x i1> %b, <3 x i7> %x) {130; CHECK-LABEL: @ctpop_sel_const_false(131; CHECK-NEXT: [[TMP1:%.*]] = call range(i7 0, 8) <3 x i7> @llvm.ctpop.v3i7(<3 x i7> [[X:%.*]])132; CHECK-NEXT: [[C:%.*]] = select <3 x i1> [[B:%.*]], <3 x i7> [[TMP1]], <3 x i7> <i7 3, i7 7, i7 0>133; CHECK-NEXT: ret <3 x i7> [[C]]134;135 %s = select <3 x i1> %b, <3 x i7> %x, <3 x i7> <i7 7, i7 -1, i7 0>136 %c = call <3 x i7> @llvm.ctpop.v3i7(<3 x i7> %s)137 ret <3 x i7> %c138}139 140define i32 @ctpop_sel_const_true_false_extra_use(i1 %b) {141; CHECK-LABEL: @ctpop_sel_const_true_false_extra_use(142; CHECK-NEXT: [[S:%.*]] = select i1 [[B:%.*]], i32 5, i32 7143; CHECK-NEXT: call void @use(i32 [[S]])144; CHECK-NEXT: [[C:%.*]] = call range(i32 2, 4) i32 @llvm.ctpop.i32(i32 [[S]])145; CHECK-NEXT: ret i32 [[C]]146;147 %s = select i1 %b, i32 5, i32 7148 call void @use(i32 %s)149 %c = call i32 @llvm.ctpop.i32(i32 %s)150 ret i32 %c151}152 153define i32 @usub_sat_rhs_const_select_all_const(i1 %b) {154; CHECK-LABEL: @usub_sat_rhs_const_select_all_const(155; CHECK-NEXT: [[C:%.*]] = select i1 [[B:%.*]], i32 0, i32 3156; CHECK-NEXT: ret i32 [[C]]157;158 %s = select i1 %b, i32 5, i32 10159 %c = call i32 @llvm.usub.sat.i32(i32 %s, i32 7)160 ret i32 %c161}162 163define i32 @usub_sat_rhs_var_select_all_const(i1 %b, i32 %x) {164; CHECK-LABEL: @usub_sat_rhs_var_select_all_const(165; CHECK-NEXT: [[S:%.*]] = select i1 [[B:%.*]], i32 5, i32 10166; CHECK-NEXT: [[C:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[S]], i32 [[X:%.*]])167; CHECK-NEXT: ret i32 [[C]]168;169 %s = select i1 %b, i32 5, i32 10170 %c = call i32 @llvm.usub.sat.i32(i32 %s, i32 %x)171 ret i32 %c172}173 174define i32 @usub_sat_rhs_const_select_one_const(i1 %b, i32 %x) {175; CHECK-LABEL: @usub_sat_rhs_const_select_one_const(176; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[X:%.*]], i32 7)177; CHECK-NEXT: [[C:%.*]] = select i1 [[B:%.*]], i32 0, i32 [[TMP1]]178; CHECK-NEXT: ret i32 [[C]]179;180 %s = select i1 %b, i32 5, i32 %x181 %c = call i32 @llvm.usub.sat.i32(i32 %s, i32 7)182 ret i32 %c183}184 185define i32 @usub_sat_rhs_const_select_no_const(i1 %b, i32 %x, i32 %y) {186; CHECK-LABEL: @usub_sat_rhs_const_select_no_const(187; CHECK-NEXT: [[S:%.*]] = select i1 [[B:%.*]], i32 [[Y:%.*]], i32 [[X:%.*]]188; CHECK-NEXT: [[C:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[S]], i32 7)189; CHECK-NEXT: ret i32 [[C]]190;191 %s = select i1 %b, i32 %y, i32 %x192 %c = call i32 @llvm.usub.sat.i32(i32 %s, i32 7)193 ret i32 %c194}195 196define i32 @usub_sat_lhs_const_select_all_const(i1 %b) {197; CHECK-LABEL: @usub_sat_lhs_const_select_all_const(198; CHECK-NEXT: [[C:%.*]] = select i1 [[B:%.*]], i32 2, i32 0199; CHECK-NEXT: ret i32 [[C]]200;201 %s = select i1 %b, i32 5, i32 10202 %c = call i32 @llvm.usub.sat.i32(i32 7, i32 %s)203 ret i32 %c204}205 206@g1 = constant <2 x i32> zeroinitializer207@g2 = external global i8208declare <2 x i32> @llvm.masked.load.v2i32.p0(ptr, i32, <2 x i1>, <2 x i32>)209 210define <2 x i32> @non_speculatable(i1 %b) {211; CHECK-LABEL: @non_speculatable(212; CHECK-NEXT: [[S:%.*]] = select i1 [[B:%.*]], ptr @g1, ptr @g2213; CHECK-NEXT: [[C:%.*]] = call <2 x i32> @llvm.masked.load.v2i32.p0(ptr nonnull align 64 [[S]], <2 x i1> <i1 true, i1 false>, <2 x i32> poison)214; CHECK-NEXT: ret <2 x i32> [[C]]215;216 %s = select i1 %b, ptr @g1, ptr @g2217 %c = call <2 x i32> @llvm.masked.load.v2i32.p0(ptr %s, i32 64, <2 x i1> <i1 true, i1 false>, <2 x i32> poison)218 ret <2 x i32> %c219}220 221declare i32 @llvm.vector.reduce.add.v2i32(<2 x i32>)222 223define i32 @vec_to_scalar_select_scalar(i1 %b) {224; CHECK-LABEL: @vec_to_scalar_select_scalar(225; CHECK-NEXT: [[C:%.*]] = select i1 [[B:%.*]], i32 3, i32 7226; CHECK-NEXT: ret i32 [[C]]227;228 %s = select i1 %b, <2 x i32> <i32 1, i32 2>, <2 x i32> <i32 3, i32 4>229 %c = call i32 @llvm.vector.reduce.add.v2i32(<2 x i32> %s)230 ret i32 %c231}232 233define i32 @vec_to_scalar_select_vector(<2 x i1> %b) {234; CHECK-LABEL: @vec_to_scalar_select_vector(235; CHECK-NEXT: [[S:%.*]] = select <2 x i1> [[B:%.*]], <2 x i32> <i32 1, i32 2>, <2 x i32> <i32 3, i32 4>236; CHECK-NEXT: [[C:%.*]] = call i32 @llvm.vector.reduce.add.v2i32(<2 x i32> [[S]])237; CHECK-NEXT: ret i32 [[C]]238;239 %s = select <2 x i1> %b, <2 x i32> <i32 1, i32 2>, <2 x i32> <i32 3, i32 4>240 %c = call i32 @llvm.vector.reduce.add.v2i32(<2 x i32> %s)241 ret i32 %c242}243 244define i8 @test_drop_noundef(i1 %cond, i8 %val) {245; CHECK-LABEL: @test_drop_noundef(246; CHECK-NEXT: entry:247; CHECK-NEXT: [[TMP0:%.*]] = call i8 @llvm.smin.i8(i8 [[VAL:%.*]], i8 0)248; CHECK-NEXT: [[RET:%.*]] = select i1 [[COND:%.*]], i8 -1, i8 [[TMP0]]249; CHECK-NEXT: ret i8 [[RET]]250;251entry:252 %sel = select i1 %cond, i8 -1, i8 %val253 %ret = call noundef i8 @llvm.smin.i8(i8 %sel, i8 0)254 ret i8 %ret255}256 257define i1 @pr85536(i32 %a) {258; CHECK-LABEL: @pr85536(259; CHECK-NEXT: entry:260; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[A:%.*]], 31261; CHECK-NEXT: [[SHL1:%.*]] = shl nsw i32 -1, [[A]]262; CHECK-NEXT: [[ZEXT:%.*]] = zext i32 [[SHL1]] to i64263; CHECK-NEXT: [[SHL2:%.*]] = shl i64 [[ZEXT]], 48264; CHECK-NEXT: [[SHR:%.*]] = ashr exact i64 [[SHL2]], 48265; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.smin.i64(i64 [[SHR]], i64 0)266; CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 65535267; CHECK-NEXT: [[RET1:%.*]] = icmp eq i64 [[TMP1]], 0268; CHECK-NEXT: [[RET:%.*]] = select i1 [[CMP1]], i1 [[RET1]], i1 false269; CHECK-NEXT: ret i1 [[RET]]270;271entry:272 %cmp1 = icmp ugt i32 %a, 30273 %shl1 = shl nsw i32 -1, %a274 %zext = zext i32 %shl1 to i64275 %shl2 = shl i64 %zext, 48276 %shr = ashr exact i64 %shl2, 48277 %sel = select i1 %cmp1, i64 -1, i64 %shr278 %smin = call noundef i64 @llvm.smin.i64(i64 %sel, i64 0)279 %masked = and i64 %smin, 65535280 %ret = icmp eq i64 %masked, 0281 ret i1 %ret282}283 284define double @test_fabs_select1(double %a) {285; CHECK-LABEL: @test_fabs_select1(286; CHECK-NEXT: [[COND:%.*]] = fcmp uno double [[A:%.*]], 0.000000e+00287; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[COND]], double 0x7FF8000000000000, double [[A]]288; CHECK-NEXT: ret double [[SEL1]]289;290 %cond = fcmp uno double %a, 0.000000e+00291 %sel1 = select i1 %cond, double 0x7FF8000000000000, double %a292 %fabs = call double @llvm.fabs.f64(double %sel1)293 %sel2 = select i1 %cond, double %fabs, double %a294 ret double %sel2295}296 297define <2 x double> @test_fabs_select1_vec(<2 x double> %a) {298; CHECK-LABEL: @test_fabs_select1_vec(299; CHECK-NEXT: [[COND:%.*]] = fcmp uno <2 x double> [[A:%.*]], zeroinitializer300; CHECK-NEXT: [[SEL2:%.*]] = select <2 x i1> [[COND]], <2 x double> splat (double 0x7FF8000000000000), <2 x double> [[A]]301; CHECK-NEXT: ret <2 x double> [[SEL2]]302;303 %cond = fcmp uno <2 x double> %a, zeroinitializer304 %sel1 = select <2 x i1> %cond, <2 x double> splat(double 0x7FF8000000000000), <2 x double> %a305 %fabs = call <2 x double> @llvm.fabs.v2f64(<2 x double> %sel1)306 %sel2 = select <2 x i1> %cond, <2 x double> %fabs, <2 x double> %a307 ret <2 x double> %sel2308}309 310define double @test_fabs_select2(double %a) {311; CHECK-LABEL: @test_fabs_select2(312; CHECK-NEXT: [[ABS1:%.*]] = call double @llvm.fabs.f64(double [[A:%.*]])313; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq double [[ABS1]], 0x7FF0000000000000314; CHECK-NEXT: [[ABS2:%.*]] = select i1 [[CMP]], double 0.000000e+00, double [[ABS1]]315; CHECK-NEXT: ret double [[ABS2]]316;317 %abs1 = call double @llvm.fabs.f64(double %a)318 %cmp = fcmp oeq double %abs1, 0x7FF0000000000000319 %sel = select i1 %cmp, double -0.000000e+00, double %abs1320 %abs2 = call double @llvm.fabs.f64(double %sel)321 ret double %abs2322}323 324; nsz flag should be dropped.325 326define double @test_fabs_select_fmf1(i1 %cond, double %a) {327; CHECK-LABEL: @test_fabs_select_fmf1(328; CHECK-NEXT: [[A:%.*]] = call double @llvm.fabs.f64(double [[A1:%.*]])329; CHECK-NEXT: [[FABS:%.*]] = select nnan ninf i1 [[COND:%.*]], double 0.000000e+00, double [[A]]330; CHECK-NEXT: ret double [[FABS]]331;332 %sel1 = select nnan ninf nsz i1 %cond, double 0.0, double %a333 %fabs = call double @llvm.fabs.f64(double %sel1)334 ret double %fabs335}336 337define double @test_fabs_select_fmf2(i1 %cond, double %a) {338; CHECK-LABEL: @test_fabs_select_fmf2(339; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.fabs.f64(double [[A:%.*]])340; CHECK-NEXT: [[SEL1:%.*]] = select nnan ninf nsz i1 [[COND:%.*]], double 0.000000e+00, double [[TMP1]]341; CHECK-NEXT: ret double [[SEL1]]342;343 %sel1 = select i1 %cond, double 0.0, double %a344 %fabs = call nnan ninf nsz double @llvm.fabs.f64(double %sel1)345 ret double %fabs346}347 348define float @test_fabs_select_multiuse(i1 %cond, float %x) {349; CHECK-LABEL: @test_fabs_select_multiuse(350; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND:%.*]], float [[X:%.*]], float 0x7FF0000000000000351; CHECK-NEXT: call void @usef32(float [[SELECT]])352; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])353; CHECK-NEXT: ret float [[FABS]]354;355 %select = select i1 %cond, float %x, float 0x7FF0000000000000356 call void @usef32(float %select)357 %fabs = call float @llvm.fabs.f32(float %select)358 ret float %fabs359}360 361define float @test_fabs_select_multiuse_both_constant(i1 %cond, float %x) {362; CHECK-LABEL: @test_fabs_select_multiuse_both_constant(363; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND:%.*]], float -1.000000e+00, float -2.000000e+00364; CHECK-NEXT: call void @usef32(float [[SELECT]])365; CHECK-NEXT: [[FABS:%.*]] = select i1 [[COND]], float 1.000000e+00, float 2.000000e+00366; CHECK-NEXT: ret float [[FABS]]367;368 %select = select i1 %cond, float -1.0, float -2.0369 call void @usef32(float %select)370 %fabs = call float @llvm.fabs.f32(float %select)371 ret float %fabs372}373 374; Negative test: Don't replace with select between vector mask and zeroinitializer.375define <16 x i1> @test_select_of_active_lane_mask_bound(i64 %base, i64 %n, i1 %cond) {376; CHECK-LABEL: @test_select_of_active_lane_mask_bound(377; CHECK-NEXT: [[S:%.*]] = select i1 [[COND:%.*]], i64 [[N:%.*]], i64 0378; CHECK-NEXT: [[MASK:%.*]] = call <16 x i1> @llvm.get.active.lane.mask.v16i1.i64(i64 [[BASE:%.*]], i64 [[S]])379; CHECK-NEXT: ret <16 x i1> [[MASK]]380;381 %s = select i1 %cond, i64 %n, i64 0382 %mask = call <16 x i1> @llvm.get.active.lane.mask.v16i1.i64(i64 %base, i64 %s)383 ret <16 x i1> %mask384}385 386define <16 x i1> @test_select_of_active_lane_mask_bound_both_constant(i64 %base, i64 %n, i1 %cond) {387; CHECK-LABEL: @test_select_of_active_lane_mask_bound_both_constant(388; CHECK-NEXT: [[MASK:%.*]] = select i1 [[COND:%.*]], <16 x i1> splat (i1 true), <16 x i1> zeroinitializer389; CHECK-NEXT: ret <16 x i1> [[MASK]]390;391 %s = select i1 %cond, i64 16, i64 0392 %mask = call <16 x i1> @llvm.get.active.lane.mask.v16i1.i64(i64 0, i64 %s)393 ret <16 x i1> %mask394}395 396define { i64, i1 } @test_select_of_overflow_intrinsic_operand(i64 %n, i1 %cond) {397; CHECK-LABEL: @test_select_of_overflow_intrinsic_operand(398; CHECK-NEXT: [[TMP1:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[N:%.*]], i64 42)399; CHECK-NEXT: [[ADD_OVERFLOW:%.*]] = select i1 [[COND:%.*]], { i64, i1 } [[TMP1]], { i64, i1 } { i64 42, i1 false }400; CHECK-NEXT: ret { i64, i1 } [[ADD_OVERFLOW]]401;402 %s = select i1 %cond, i64 %n, i64 0403 %add_overflow = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %s, i64 42)404 ret { i64, i1 } %add_overflow405}406