473 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -S -passes=instcombine < %s | FileCheck %s3 4; This is the canonical form for a type-changing min/max.5define double @t1(float %a) {6; CHECK-LABEL: @t1(7; CHECK-NEXT: [[DOTINV:%.*]] = fcmp oge float [[A:%.*]], 5.000000e+008; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[DOTINV]], float 5.000000e+00, float [[A]]9; CHECK-NEXT: [[TMP2:%.*]] = fpext float [[TMP1]] to double10; CHECK-NEXT: ret double [[TMP2]]11;12 %1 = fcmp ult float %a, 5.013 %2 = select i1 %1, float %a, float 5.014 %3 = fpext float %2 to double15 ret double %316}17 18; Check this is converted into canonical form, as above.19define double @t2(float %a) {20; CHECK-LABEL: @t2(21; CHECK-NEXT: [[DOTINV:%.*]] = fcmp oge float [[A:%.*]], 5.000000e+0022; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[DOTINV]], float 5.000000e+00, float [[A]]23; CHECK-NEXT: [[TMP2:%.*]] = fpext float [[TMP1]] to double24; CHECK-NEXT: ret double [[TMP2]]25;26 %1 = fcmp ult float %a, 5.027 %2 = fpext float %a to double28 %3 = select i1 %1, double %2, double 5.029 ret double %330}31 32; Same again, with trunc.33define float @t4(double %a) {34; CHECK-LABEL: @t4(35; CHECK-NEXT: [[DOTINV:%.*]] = fcmp oge double [[A:%.*]], 5.000000e+0036; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[DOTINV]], double 5.000000e+00, double [[A]]37; CHECK-NEXT: [[TMP2:%.*]] = fptrunc double [[TMP1]] to float38; CHECK-NEXT: ret float [[TMP2]]39;40 %1 = fcmp ult double %a, 5.041 %2 = fptrunc double %a to float42 %3 = select i1 %1, float %2, float 5.043 ret float %344}45 46; different values, should not be converted.47define double @t5(float %a) {48; CHECK-LABEL: @t5(49; CHECK-NEXT: [[TMP1:%.*]] = fcmp ult float [[A:%.*]], 5.000000e+0050; CHECK-NEXT: [[TMP2:%.*]] = fpext float [[A]] to double51; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], double [[TMP2]], double 5.001000e+0052; CHECK-NEXT: ret double [[TMP3]]53;54 %1 = fcmp ult float %a, 5.055 %2 = fpext float %a to double56 %3 = select i1 %1, double %2, double 5.00157 ret double %358}59 60; PR5735761 62define float @not_maxnum(float %x) {63; CHECK-LABEL: @not_maxnum(64; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float [[X:%.*]], 0.000000e+0065; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], float -0.000000e+00, float [[X]]66; CHECK-NEXT: ret float [[SEL]]67;68 %cmp = fcmp olt float %x, 0.069 %sel = select i1 %cmp, float -0.0, float %x70 ret float %sel71}72 73; From IEEE754: "Comparisons shall ignore the sign of zero (so +0 = -0)."74; So the compare constant may be treated as +0.0, and we sink the fpext.75 76define double @t6(float %a) {77; CHECK-LABEL: @t6(78; CHECK-NEXT: [[DOTINV:%.*]] = fcmp oge float [[A:%.*]], 0.000000e+0079; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[DOTINV]], float 0.000000e+00, float [[A]]80; CHECK-NEXT: [[TMP2:%.*]] = fpext float [[TMP1]] to double81; CHECK-NEXT: ret double [[TMP2]]82;83 %1 = fcmp ult float %a, -0.084 %2 = fpext float %a to double85 %3 = select i1 %1, double %2, double 0.086 ret double %387}88 89; TODO: Move the select ahead of the fpext because it's a narrower op.90; This works as long as the wide constant can be represented exactly in the narrow type.91 92define double @t7(float %a) {93; CHECK-LABEL: @t7(94; CHECK-NEXT: [[TMP1:%.*]] = fcmp ult float [[A:%.*]], 0.000000e+0095; CHECK-NEXT: [[TMP2:%.*]] = fpext float [[A]] to double96; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], double [[TMP2]], double -0.000000e+0097; CHECK-NEXT: ret double [[TMP3]]98;99 %1 = fcmp ult float %a, 0.0100 %2 = fpext float %a to double101 %3 = select i1 %1, double %2, double -0.0102 ret double %3103}104 105; min(min(x, 0.0), 0.0) --> min(x, 0.0)106 107define float @fmin_fmin_zero_mismatch(float %x) {108; CHECK-LABEL: @fmin_fmin_zero_mismatch(109; CHECK-NEXT: [[CMP1:%.*]] = fcmp olt float [[X:%.*]], 0.000000e+00110; CHECK-NEXT: [[MIN2:%.*]] = select i1 [[CMP1]], float [[X]], float 0.000000e+00111; CHECK-NEXT: ret float [[MIN2]]112;113 %cmp1 = fcmp olt float %x, -0.0114 %min1 = select i1 %cmp1, float %x, float 0.0115 %cmp2 = fcmp olt float %min1, 0.0116 %min2 = select i1 %cmp2, float %min1, float 0.0117 ret float %min2118}119 120; max(max(x, -0.0), -0.0) --> max(x, -0.0)121define float @fmax_fmax_zero_mismatch(float %x) {122; CHECK-LABEL: @fmax_fmax_zero_mismatch(123; CHECK-NEXT: [[CMP1:%.*]] = fcmp ogt float [[X:%.*]], 0.000000e+00124; CHECK-NEXT: [[MAX1:%.*]] = select i1 [[CMP1]], float [[X]], float -0.000000e+00125; CHECK-NEXT: ret float [[MAX1]]126;127 %cmp1 = fcmp ogt float %x, 0.0128 %max1 = select i1 %cmp1, float %x, float -0.0129 %cmp2 = fcmp ogt float 0.0, %max1130 %max2 = select i1 %cmp2, float -0.0, float %max1131 ret float %max2132}133 134define i64 @t8(float %a) {135; CHECK-LABEL: @t8(136; CHECK-NEXT: [[DOTINV:%.*]] = fcmp oge float [[A:%.*]], 5.000000e+00137; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[DOTINV]], float 5.000000e+00, float [[A]]138; CHECK-NEXT: [[TMP2:%.*]] = fptoui float [[TMP1]] to i64139; CHECK-NEXT: ret i64 [[TMP2]]140;141 %1 = fcmp ult float %a, 5.0142 %2 = fptoui float %a to i64143 %3 = select i1 %1, i64 %2, i64 5144 ret i64 %3145}146 147define i8 @t9(float %a) {148; CHECK-LABEL: @t9(149; CHECK-NEXT: [[DOTINV:%.*]] = fcmp oge float [[A:%.*]], 0.000000e+00150; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[DOTINV]], float 0.000000e+00, float [[A]]151; CHECK-NEXT: [[TMP2:%.*]] = fptosi float [[TMP1]] to i8152; CHECK-NEXT: ret i8 [[TMP2]]153;154 %1 = fcmp ult float %a, 0.0155 %2 = fptosi float %a to i8156 %3 = select i1 %1, i8 %2, i8 0157 ret i8 %3158}159 160 ; Either operand could be NaN, but fast modifier applied.161define i8 @t11(float %a, float %b) {162; CHECK-LABEL: @t11(163; CHECK-NEXT: [[DOTV:%.*]] = call nnan ninf float @llvm.minnum.f32(float [[B:%.*]], float [[A:%.*]])164; CHECK-NEXT: [[TMP1:%.*]] = fptosi float [[DOTV]] to i8165; CHECK-NEXT: ret i8 [[TMP1]]166;167 %1 = fcmp fast ult float %b, %a168 %2 = fptosi float %a to i8169 %3 = fptosi float %b to i8170 %4 = select i1 %1, i8 %3, i8 %2171 ret i8 %4172}173 174; Either operand could be NaN, but nnan modifier applied.175define i8 @t12(float %a, float %b) {176; CHECK-LABEL: @t12(177; CHECK-NEXT: [[DOTV:%.*]] = call nnan float @llvm.minnum.f32(float [[B:%.*]], float [[A:%.*]])178; CHECK-NEXT: [[TMP1:%.*]] = fptosi float [[DOTV]] to i8179; CHECK-NEXT: ret i8 [[TMP1]]180;181 %1 = fcmp nnan ult float %b, %a182 %2 = fptosi float %a to i8183 %3 = fptosi float %b to i8184 %4 = select i1 %1, i8 %3, i8 %2185 ret i8 %4186}187 188; Float and int values do not match.189define i8 @t13(float %a) {190; CHECK-LABEL: @t13(191; CHECK-NEXT: [[TMP1:%.*]] = fcmp ult float [[A:%.*]], 1.500000e+00192; CHECK-NEXT: [[TMP2:%.*]] = fptosi float [[A]] to i8193; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i8 [[TMP2]], i8 1194; CHECK-NEXT: ret i8 [[TMP3]]195;196 %1 = fcmp ult float %a, 1.5197 %2 = fptosi float %a to i8198 %3 = select i1 %1, i8 %2, i8 1199 ret i8 %3200}201 202; %a could be -0.0, but it doesn't matter because the conversion to int is the same for 0.0 or -0.0.203define i8 @t14(float %a) {204; CHECK-LABEL: @t14(205; CHECK-NEXT: [[DOTINV:%.*]] = fcmp oge float [[A:%.*]], 0.000000e+00206; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[DOTINV]], float 0.000000e+00, float [[A]]207; CHECK-NEXT: [[TMP2:%.*]] = fptosi float [[TMP1]] to i8208; CHECK-NEXT: ret i8 [[TMP2]]209;210 %1 = fcmp ule float %a, 0.0211 %2 = fptosi float %a to i8212 %3 = select i1 %1, i8 %2, i8 0213 ret i8 %3214}215 216define i8 @t14_commute(float %a) {217; CHECK-LABEL: @t14_commute(218; CHECK-NEXT: [[TMP1:%.*]] = fcmp ogt float [[A:%.*]], 0.000000e+00219; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], float [[A]], float 0.000000e+00220; CHECK-NEXT: [[TMP3:%.*]] = fptosi float [[TMP2]] to i8221; CHECK-NEXT: ret i8 [[TMP3]]222;223 %1 = fcmp ule float %a, 0.0224 %2 = fptosi float %a to i8225 %3 = select i1 %1, i8 0, i8 %2226 ret i8 %3227}228 229define i8 @t15(float %a) {230; CHECK-LABEL: @t15(231; CHECK-NEXT: [[DOTINV:%.*]] = fcmp nsz oge float [[A:%.*]], 0.000000e+00232; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[DOTINV]], float 0.000000e+00, float [[A]]233; CHECK-NEXT: [[TMP2:%.*]] = fptosi float [[TMP1]] to i8234; CHECK-NEXT: ret i8 [[TMP2]]235;236 %1 = fcmp nsz ule float %a, 0.0237 %2 = fptosi float %a to i8238 %3 = select i1 %1, i8 %2, i8 0239 ret i8 %3240}241 242define double @t16(i32 %x) {243; CHECK-LABEL: @t16(244; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X:%.*]], 0245; CHECK-NEXT: [[CST:%.*]] = sitofp i32 [[X]] to double246; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], double [[CST]], double 5.000000e-01247; CHECK-NEXT: ret double [[SEL]]248;249 %cmp = icmp sgt i32 %x, 0250 %cst = sitofp i32 %x to double251 %sel = select i1 %cmp, double %cst, double 5.000000e-01252 ret double %sel253}254 255define double @t17(i32 %x) {256; CHECK-LABEL: @t17(257; CHECK-NEXT: [[SEL1:%.*]] = call i32 @llvm.smax.i32(i32 [[X:%.*]], i32 2)258; CHECK-NEXT: [[SEL:%.*]] = uitofp nneg i32 [[SEL1]] to double259; CHECK-NEXT: ret double [[SEL]]260;261 %cmp = icmp sgt i32 %x, 2262 %cst = sitofp i32 %x to double263 %sel = select i1 %cmp, double %cst, double 2.0264 ret double %sel265}266 267define float @fneg_fmax(float %x, float %y) {268; CHECK-LABEL: @fneg_fmax(269; CHECK-NEXT: [[COND:%.*]] = fcmp nnan olt float [[X:%.*]], [[Y:%.*]]270; CHECK-NEXT: [[MAX_V:%.*]] = select i1 [[COND]], float [[X]], float [[Y]]271; CHECK-NEXT: [[MAX:%.*]] = fneg float [[MAX_V]]272; CHECK-NEXT: ret float [[MAX]]273;274 %n1 = fneg float %x275 %n2 = fneg float %y276 %cond = fcmp nnan ogt float %n1, %n2277 %max = select i1 %cond, float %n1, float %n2278 ret float %max279}280 281define <2 x float> @fsub_fmax(<2 x float> %x, <2 x float> %y) {282; CHECK-LABEL: @fsub_fmax(283; CHECK-NEXT: [[COND_INV:%.*]] = fcmp nnan nsz ogt <2 x float> [[X:%.*]], [[Y:%.*]]284; CHECK-NEXT: [[MAX_V:%.*]] = select nnan <2 x i1> [[COND_INV]], <2 x float> [[Y]], <2 x float> [[X]]285; CHECK-NEXT: [[MAX:%.*]] = fneg <2 x float> [[MAX_V]]286; CHECK-NEXT: ret <2 x float> [[MAX]]287;288 %n1 = fsub <2 x float> <float -0.0, float -0.0>, %x289 %n2 = fsub <2 x float> <float -0.0, float -0.0>, %y290 %cond = fcmp nsz nnan uge <2 x float> %n1, %n2291 %max = select <2 x i1> %cond, <2 x float> %n1, <2 x float> %n2292 ret <2 x float> %max293}294 295define <2 x double> @fsub_fmin(<2 x double> %x, <2 x double> %y) {296; CHECK-LABEL: @fsub_fmin(297; CHECK-NEXT: [[COND:%.*]] = fcmp nnan ogt <2 x double> [[X:%.*]], [[Y:%.*]]298; CHECK-NEXT: [[MAX_V:%.*]] = select <2 x i1> [[COND]], <2 x double> [[X]], <2 x double> [[Y]]299; CHECK-NEXT: [[MAX:%.*]] = fneg <2 x double> [[MAX_V]]300; CHECK-NEXT: ret <2 x double> [[MAX]]301;302 %n1 = fsub <2 x double> <double -0.0, double -0.0>, %x303 %n2 = fsub <2 x double> <double -0.0, double -0.0>, %y304 %cond = fcmp nnan olt <2 x double> %n1, %n2305 %max = select <2 x i1> %cond, <2 x double> %n1, <2 x double> %n2306 ret <2 x double> %max307}308 309define double @fneg_fmin(double %x, double %y) {310; CHECK-LABEL: @fneg_fmin(311; CHECK-NEXT: [[COND_INV:%.*]] = fcmp nnan nsz olt double [[X:%.*]], [[Y:%.*]]312; CHECK-NEXT: [[MAX_V:%.*]] = select nnan i1 [[COND_INV]], double [[Y]], double [[X]]313; CHECK-NEXT: [[MAX:%.*]] = fneg double [[MAX_V]]314; CHECK-NEXT: ret double [[MAX]]315;316 %n1 = fneg double %x317 %n2 = fneg double %y318 %cond = fcmp nsz nnan ule double %n1, %n2319 %max = select i1 %cond, double %n1, double %n2320 ret double %max321}322 323define float @maxnum_ogt_fmf_on_select(float %a, float %b) {324; CHECK-LABEL: @maxnum_ogt_fmf_on_select(325; CHECK-NEXT: [[F:%.*]] = call nsz float @llvm.maxnum.f32(float [[A:%.*]], float [[B:%.*]])326; CHECK-NEXT: ret float [[F]]327;328 %cond = fcmp ogt float %a, %b329 %f = select nnan nsz i1 %cond, float %a, float %b330 ret float %f331}332 333define <2 x float> @maxnum_oge_fmf_on_select(<2 x float> %a, <2 x float> %b) {334; CHECK-LABEL: @maxnum_oge_fmf_on_select(335; CHECK-NEXT: [[F:%.*]] = call nsz <2 x float> @llvm.maxnum.v2f32(<2 x float> [[A:%.*]], <2 x float> [[B:%.*]])336; CHECK-NEXT: ret <2 x float> [[F]]337;338 %cond = fcmp oge <2 x float> %a, %b339 %f = select ninf nnan nsz <2 x i1> %cond, <2 x float> %a, <2 x float> %b340 ret <2 x float> %f341}342 343define float @maxnum_ogt_fmf_on_fcmp(float %a, float %b) {344; CHECK-LABEL: @maxnum_ogt_fmf_on_fcmp(345; CHECK-NEXT: [[COND:%.*]] = fcmp nnan nsz ogt float [[A:%.*]], [[B:%.*]]346; CHECK-NEXT: [[F:%.*]] = select i1 [[COND]], float [[A]], float [[B]]347; CHECK-NEXT: ret float [[F]]348;349 %cond = fcmp nnan nsz ogt float %a, %b350 %f = select i1 %cond, float %a, float %b351 ret float %f352}353 354define <2 x float> @maxnum_oge_fmf_on_fcmp(<2 x float> %a, <2 x float> %b) {355; CHECK-LABEL: @maxnum_oge_fmf_on_fcmp(356; CHECK-NEXT: [[COND:%.*]] = fcmp nnan ninf nsz oge <2 x float> [[A:%.*]], [[B:%.*]]357; CHECK-NEXT: [[F:%.*]] = select <2 x i1> [[COND]], <2 x float> [[A]], <2 x float> [[B]]358; CHECK-NEXT: ret <2 x float> [[F]]359;360 %cond = fcmp ninf nnan nsz oge <2 x float> %a, %b361 %f = select <2 x i1> %cond, <2 x float> %a, <2 x float> %b362 ret <2 x float> %f363}364 365define float @maxnum_no_nsz(float %a, float %b) {366; CHECK-LABEL: @maxnum_no_nsz(367; CHECK-NEXT: [[COND:%.*]] = fcmp ogt float [[A:%.*]], [[B:%.*]]368; CHECK-NEXT: [[F:%.*]] = select nnan i1 [[COND]], float [[A]], float [[B]]369; CHECK-NEXT: ret float [[F]]370;371 %cond = fcmp ogt float %a, %b372 %f = select nnan i1 %cond, float %a, float %b373 ret float %f374}375 376define float @maxnum_no_nnan(float %a, float %b) {377; CHECK-LABEL: @maxnum_no_nnan(378; CHECK-NEXT: [[COND:%.*]] = fcmp oge float [[A:%.*]], [[B:%.*]]379; CHECK-NEXT: [[F:%.*]] = select nsz i1 [[COND]], float [[A]], float [[B]]380; CHECK-NEXT: ret float [[F]]381;382 %cond = fcmp oge float %a, %b383 %f = select nsz i1 %cond, float %a, float %b384 ret float %f385}386 387define float @minnum_olt_fmf_on_select_both_ninf(float %a, float %b) {388; CHECK-LABEL: @minnum_olt_fmf_on_select_both_ninf(389; CHECK-NEXT: [[F:%.*]] = call ninf nsz float @llvm.minnum.f32(float [[A:%.*]], float [[B:%.*]])390; CHECK-NEXT: ret float [[F]]391;392 %cond = fcmp ninf olt float %a, %b393 %f = select nnan ninf nsz i1 %cond, float %a, float %b394 ret float %f395}396 397define float @minnum_olt_fmf_on_select(float %a, float %b) {398; CHECK-LABEL: @minnum_olt_fmf_on_select(399; CHECK-NEXT: [[F:%.*]] = call nsz float @llvm.minnum.f32(float [[A:%.*]], float [[B:%.*]])400; CHECK-NEXT: ret float [[F]]401;402 %cond = fcmp olt float %a, %b403 %f = select nnan nsz i1 %cond, float %a, float %b404 ret float %f405}406 407define <2 x float> @minnum_ole_fmf_on_select(<2 x float> %a, <2 x float> %b) {408; CHECK-LABEL: @minnum_ole_fmf_on_select(409; CHECK-NEXT: [[F:%.*]] = call nsz <2 x float> @llvm.minnum.v2f32(<2 x float> [[A:%.*]], <2 x float> [[B:%.*]])410; CHECK-NEXT: ret <2 x float> [[F]]411;412 %cond = fcmp ole <2 x float> %a, %b413 %f = select ninf nnan nsz <2 x i1> %cond, <2 x float> %a, <2 x float> %b414 ret <2 x float> %f415}416 417define float @minnum_olt_fmf_on_fcmp(float %a, float %b) {418; CHECK-LABEL: @minnum_olt_fmf_on_fcmp(419; CHECK-NEXT: [[COND:%.*]] = fcmp nnan nsz olt float [[A:%.*]], [[B:%.*]]420; CHECK-NEXT: [[F:%.*]] = select i1 [[COND]], float [[A]], float [[B]]421; CHECK-NEXT: ret float [[F]]422;423 %cond = fcmp nnan nsz olt float %a, %b424 %f = select i1 %cond, float %a, float %b425 ret float %f426}427 428define <2 x float> @minnum_ole_fmf_on_fcmp(<2 x float> %a, <2 x float> %b) {429; CHECK-LABEL: @minnum_ole_fmf_on_fcmp(430; CHECK-NEXT: [[COND:%.*]] = fcmp nnan ninf nsz ole <2 x float> [[A:%.*]], [[B:%.*]]431; CHECK-NEXT: [[F:%.*]] = select <2 x i1> [[COND]], <2 x float> [[A]], <2 x float> [[B]]432; CHECK-NEXT: ret <2 x float> [[F]]433;434 %cond = fcmp ninf nnan nsz ole <2 x float> %a, %b435 %f = select <2 x i1> %cond, <2 x float> %a, <2 x float> %b436 ret <2 x float> %f437}438 439define float @minnum_no_nsz(float %a, float %b) {440; CHECK-LABEL: @minnum_no_nsz(441; CHECK-NEXT: [[COND:%.*]] = fcmp olt float [[A:%.*]], [[B:%.*]]442; CHECK-NEXT: [[F:%.*]] = select nnan i1 [[COND]], float [[A]], float [[B]]443; CHECK-NEXT: ret float [[F]]444;445 %cond = fcmp olt float %a, %b446 %f = select nnan i1 %cond, float %a, float %b447 ret float %f448}449 450define float @minnum_no_nnan(float %a, float %b) {451; CHECK-LABEL: @minnum_no_nnan(452; CHECK-NEXT: [[COND:%.*]] = fcmp ole float [[A:%.*]], [[B:%.*]]453; CHECK-NEXT: [[F:%.*]] = select nsz i1 [[COND]], float [[A]], float [[B]]454; CHECK-NEXT: ret float [[F]]455;456 %cond = fcmp ole float %a, %b457 %f = select nsz i1 %cond, float %a, float %b458 ret float %f459}460 461define float @pr64937_preserve_min_idiom(float %a) {462; CHECK-LABEL: @pr64937_preserve_min_idiom(463; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan olt float [[A:%.*]], 3.276700e+04464; CHECK-NEXT: [[SEL:%.*]] = select nnan i1 [[CMP]], float [[A]], float 3.276700e+04465; CHECK-NEXT: [[RES:%.*]] = fmul nnan float [[SEL]], 6.553600e+04466; CHECK-NEXT: ret float [[RES]]467;468 %cmp = fcmp nnan olt float %a, 3.276700e+04469 %sel = select nnan i1 %cmp, float %a, float 3.276700e+04470 %res = fmul nnan float %sel, 6.553600e+04471 ret float %res472}473