482 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -S -passes=instcombine < %s | FileCheck %s3 4declare float @llvm.maxnum.f32(float, float)5declare <2 x float> @llvm.maxnum.v2f32(<2 x float>, <2 x float>)6declare <4 x float> @llvm.maxnum.v4f32(<4 x float>, <4 x float>)7 8declare double @llvm.maxnum.f64(double, double)9declare <2 x double> @llvm.maxnum.v2f64(<2 x double>, <2 x double>)10 11define float @constant_fold_maxnum_f32() {12; CHECK-LABEL: @constant_fold_maxnum_f32(13; CHECK-NEXT: ret float 2.000000e+0014;15 %x = call float @llvm.maxnum.f32(float 1.0, float 2.0)16 ret float %x17}18 19define float @constant_fold_maxnum_f32_inv() {20; CHECK-LABEL: @constant_fold_maxnum_f32_inv(21; CHECK-NEXT: ret float 2.000000e+0022;23 %x = call float @llvm.maxnum.f32(float 2.0, float 1.0)24 ret float %x25}26 27define float @constant_fold_maxnum_f32_nan0() {28; CHECK-LABEL: @constant_fold_maxnum_f32_nan0(29; CHECK-NEXT: ret float 2.000000e+0030;31 %x = call float @llvm.maxnum.f32(float 0x7FF8000000000000, float 2.0)32 ret float %x33}34 35define float @constant_fold_maxnum_f32_nan1() {36; CHECK-LABEL: @constant_fold_maxnum_f32_nan1(37; CHECK-NEXT: ret float 2.000000e+0038;39 %x = call float @llvm.maxnum.f32(float 2.0, float 0x7FF8000000000000)40 ret float %x41}42 43define float @constant_fold_maxnum_f32_nan_nan() {44; CHECK-LABEL: @constant_fold_maxnum_f32_nan_nan(45; CHECK-NEXT: ret float 0x7FF800000000000046;47 %x = call float @llvm.maxnum.f32(float 0x7FF8000000000000, float 0x7FF8000000000000)48 ret float %x49}50 51define float @constant_fold_maxnum_f32_p0_p0() {52; CHECK-LABEL: @constant_fold_maxnum_f32_p0_p0(53; CHECK-NEXT: ret float 0.000000e+0054;55 %x = call float @llvm.maxnum.f32(float 0.0, float 0.0)56 ret float %x57}58 59define float @constant_fold_maxnum_f32_p0_n0() {60; CHECK-LABEL: @constant_fold_maxnum_f32_p0_n0(61; CHECK-NEXT: ret float 0.000000e+0062;63 %x = call float @llvm.maxnum.f32(float 0.0, float -0.0)64 ret float %x65}66 67define float @constant_fold_maxnum_f32_n0_p0() {68; CHECK-LABEL: @constant_fold_maxnum_f32_n0_p0(69; CHECK-NEXT: ret float 0.000000e+0070;71 %x = call float @llvm.maxnum.f32(float -0.0, float 0.0)72 ret float %x73}74 75define float @constant_fold_maxnum_f32_n0_n0() {76; CHECK-LABEL: @constant_fold_maxnum_f32_n0_n0(77; CHECK-NEXT: ret float -0.000000e+0078;79 %x = call float @llvm.maxnum.f32(float -0.0, float -0.0)80 ret float %x81}82 83define <4 x float> @constant_fold_maxnum_v4f32() {84; CHECK-LABEL: @constant_fold_maxnum_v4f32(85; CHECK-NEXT: ret <4 x float> <float 2.000000e+00, float 8.000000e+00, float 1.000000e+01, float 9.000000e+00>86;87 %x = call <4 x float> @llvm.maxnum.v4f32(<4 x float> <float 1.0, float 8.0, float 3.0, float 9.0>, <4 x float> <float 2.0, float 2.0, float 10.0, float 5.0>)88 ret <4 x float> %x89}90 91define double @constant_fold_maxnum_f64() {92; CHECK-LABEL: @constant_fold_maxnum_f64(93; CHECK-NEXT: ret double 2.000000e+0094;95 %x = call double @llvm.maxnum.f64(double 1.0, double 2.0)96 ret double %x97}98 99define double @constant_fold_maxnum_f64_nan0() {100; CHECK-LABEL: @constant_fold_maxnum_f64_nan0(101; CHECK-NEXT: ret double 2.000000e+00102;103 %x = call double @llvm.maxnum.f64(double 0x7FF8000000000000, double 2.0)104 ret double %x105}106 107define double @constant_fold_maxnum_f64_nan1() {108; CHECK-LABEL: @constant_fold_maxnum_f64_nan1(109; CHECK-NEXT: ret double 2.000000e+00110;111 %x = call double @llvm.maxnum.f64(double 2.0, double 0x7FF8000000000000)112 ret double %x113}114 115define double @constant_fold_maxnum_f64_nan_nan() {116; CHECK-LABEL: @constant_fold_maxnum_f64_nan_nan(117; CHECK-NEXT: ret double 0x7FF8000000000000118;119 %x = call double @llvm.maxnum.f64(double 0x7FF8000000000000, double 0x7FF8000000000000)120 ret double %x121}122 123define float @canonicalize_constant_maxnum_f32(float %x) {124; CHECK-LABEL: @canonicalize_constant_maxnum_f32(125; CHECK-NEXT: [[Y:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float 1.000000e+00)126; CHECK-NEXT: ret float [[Y]]127;128 %y = call float @llvm.maxnum.f32(float 1.0, float %x)129 ret float %y130}131 132define float @maxnum_f32_nan_val(float %x) {133; CHECK-LABEL: @maxnum_f32_nan_val(134; CHECK-NEXT: ret float [[X:%.*]]135;136 %y = call float @llvm.maxnum.f32(float 0x7FF8000000000000, float %x)137 ret float %y138}139 140define float @maxnum_f32_val_nan(float %x) {141; CHECK-LABEL: @maxnum_f32_val_nan(142; CHECK-NEXT: ret float [[X:%.*]]143;144 %y = call float @llvm.maxnum.f32(float %x, float 0x7FF8000000000000)145 ret float %y146}147 148define float @maxnum_f32_1_maxnum_val_p0(float %x) {149; CHECK-LABEL: @maxnum_f32_1_maxnum_val_p0(150; CHECK-NEXT: [[Z:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float 1.000000e+00)151; CHECK-NEXT: ret float [[Z]]152;153 %y = call float @llvm.maxnum.f32(float %x, float 0.0)154 %z = call float @llvm.maxnum.f32(float %y, float 1.0)155 ret float %z156}157 158define float @maxnum_f32_1_maxnum_p0_val_fast(float %x) {159; CHECK-LABEL: @maxnum_f32_1_maxnum_p0_val_fast(160; CHECK-NEXT: [[Z:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float 1.000000e+00)161; CHECK-NEXT: ret float [[Z]]162;163 %y = call float @llvm.maxnum.f32(float 0.0, float %x)164 %z = call fast float @llvm.maxnum.f32(float %y, float 1.0)165 ret float %z166}167 168define float @minnum_f32_1_maxnum_p0_val_fmf1(float %x) {169; CHECK-LABEL: @minnum_f32_1_maxnum_p0_val_fmf1(170; CHECK-NEXT: [[Z:%.*]] = call nnan float @llvm.maxnum.f32(float [[X:%.*]], float 1.000000e+00)171; CHECK-NEXT: ret float [[Z]]172;173 %y = call nnan float @llvm.maxnum.f32(float 0.0, float %x)174 %z = call nnan ninf float @llvm.maxnum.f32(float %y, float 1.0)175 ret float %z176}177 178define float @minnum_f32_1_maxnum_p0_val_fmf2(float %x) {179; CHECK-LABEL: @minnum_f32_1_maxnum_p0_val_fmf2(180; CHECK-NEXT: [[Z:%.*]] = call ninf float @llvm.maxnum.f32(float [[X:%.*]], float 1.000000e+00)181; CHECK-NEXT: ret float [[Z]]182;183 %y = call nnan ninf float @llvm.maxnum.f32(float 0.0, float %x)184 %z = call ninf float @llvm.maxnum.f32(float %y, float 1.0)185 ret float %z186}187 188define float @minnum_f32_1_maxnum_p0_val_fmf3(float %x) {189; CHECK-LABEL: @minnum_f32_1_maxnum_p0_val_fmf3(190; CHECK-NEXT: [[Z:%.*]] = call nnan ninf float @llvm.maxnum.f32(float [[X:%.*]], float 1.000000e+00)191; CHECK-NEXT: ret float [[Z]]192;193 %y = call ninf nnan float @llvm.maxnum.f32(float 0.0, float %x)194 %z = call ninf nnan float @llvm.maxnum.f32(float %y, float 1.0)195 ret float %z196}197 198define float @maxnum_f32_p0_maxnum_val_n0(float %x) {199; CHECK-LABEL: @maxnum_f32_p0_maxnum_val_n0(200; CHECK-NEXT: [[Z:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float 0.000000e+00)201; CHECK-NEXT: ret float [[Z]]202;203 %y = call float @llvm.maxnum.f32(float %x, float -0.0)204 %z = call float @llvm.maxnum.f32(float %y, float 0.0)205 ret float %z206}207 208define float @maxnum_f32_1_maxnum_p0_val(float %x) {209; CHECK-LABEL: @maxnum_f32_1_maxnum_p0_val(210; CHECK-NEXT: [[Z:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float 1.000000e+00)211; CHECK-NEXT: ret float [[Z]]212;213 %y = call float @llvm.maxnum.f32(float 0.0, float %x)214 %z = call float @llvm.maxnum.f32(float %y, float 1.0)215 ret float %z216}217 218define <2 x float> @maxnum_f32_1_maxnum_val_p0_val_v2f32(<2 x float> %x) {219; CHECK-LABEL: @maxnum_f32_1_maxnum_val_p0_val_v2f32(220; CHECK-NEXT: [[Z:%.*]] = call <2 x float> @llvm.maxnum.v2f32(<2 x float> [[X:%.*]], <2 x float> splat (float 1.000000e+00))221; CHECK-NEXT: ret <2 x float> [[Z]]222;223 %y = call <2 x float> @llvm.maxnum.v2f32(<2 x float> %x, <2 x float> zeroinitializer)224 %z = call <2 x float> @llvm.maxnum.v2f32(<2 x float> %y, <2 x float><float 1.0, float 1.0>)225 ret <2 x float> %z226}227 228define float @maxnum4(float %x, float %y, float %z, float %w) {229; CHECK-LABEL: @maxnum4(230; CHECK-NEXT: [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])231; CHECK-NEXT: [[B:%.*]] = call float @llvm.maxnum.f32(float [[Z:%.*]], float [[W:%.*]])232; CHECK-NEXT: [[C:%.*]] = call float @llvm.maxnum.f32(float [[A]], float [[B]])233; CHECK-NEXT: ret float [[C]]234;235 %a = call float @llvm.maxnum.f32(float %x, float %y)236 %b = call float @llvm.maxnum.f32(float %z, float %w)237 %c = call float @llvm.maxnum.f32(float %a, float %b)238 ret float %c239}240 241; PR37404 - https://bugs.llvm.org/show_bug.cgi?id=37404242 243define <2 x float> @neg_neg(<2 x float> %x, <2 x float> %y) {244; CHECK-LABEL: @neg_neg(245; CHECK-NEXT: [[TMP1:%.*]] = call <2 x float> @llvm.minnum.v2f32(<2 x float> [[X:%.*]], <2 x float> [[Y:%.*]])246; CHECK-NEXT: [[R:%.*]] = fneg <2 x float> [[TMP1]]247; CHECK-NEXT: ret <2 x float> [[R]]248;249 %negx = fsub <2 x float> <float -0.0, float -0.0>, %x250 %negy = fsub <2 x float> <float -0.0, float -0.0>, %y251 %r = call <2 x float> @llvm.maxnum.v2f32(<2 x float> %negx, <2 x float> %negy)252 ret <2 x float> %r253}254 255; FMF is not required, but it should be propagated from the intrinsic (not the fnegs).256 257define float @neg_neg_vec_fmf(float %x, float %y) {258; CHECK-LABEL: @neg_neg_vec_fmf(259; CHECK-NEXT: [[TMP1:%.*]] = call fast float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])260; CHECK-NEXT: [[R:%.*]] = fneg fast float [[TMP1]]261; CHECK-NEXT: ret float [[R]]262;263 %negx = fsub arcp float -0.0, %x264 %negy = fsub afn float -0.0, %y265 %r = call fast float @llvm.maxnum.f32(float %negx, float %negy)266 ret float %r267}268 269define float @unary_neg_neg_vec_fmf(float %x, float %y) {270; CHECK-LABEL: @unary_neg_neg_vec_fmf(271; CHECK-NEXT: [[TMP1:%.*]] = call fast float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])272; CHECK-NEXT: [[R:%.*]] = fneg fast float [[TMP1]]273; CHECK-NEXT: ret float [[R]]274;275 %negx = fneg arcp float %x276 %negy = fneg afn float %y277 %r = call fast float @llvm.maxnum.f32(float %negx, float %negy)278 ret float %r279}280 281; 1 extra use of an intermediate value should still allow the fold,282; but 2 would require more instructions than we started with.283 284declare void @use(float)285define float @neg_neg_extra_use_x(float %x, float %y) {286; CHECK-LABEL: @neg_neg_extra_use_x(287; CHECK-NEXT: [[NEGX:%.*]] = fneg float [[X:%.*]]288; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.minnum.f32(float [[X]], float [[Y:%.*]])289; CHECK-NEXT: [[R:%.*]] = fneg float [[TMP1]]290; CHECK-NEXT: call void @use(float [[NEGX]])291; CHECK-NEXT: ret float [[R]]292;293 %negx = fsub float -0.0, %x294 %negy = fsub float -0.0, %y295 %r = call float @llvm.maxnum.f32(float %negx, float %negy)296 call void @use(float %negx)297 ret float %r298}299 300define float @unary_neg_neg_extra_use_x(float %x, float %y) {301; CHECK-LABEL: @unary_neg_neg_extra_use_x(302; CHECK-NEXT: [[NEGX:%.*]] = fneg float [[X:%.*]]303; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.minnum.f32(float [[X]], float [[Y:%.*]])304; CHECK-NEXT: [[R:%.*]] = fneg float [[TMP1]]305; CHECK-NEXT: call void @use(float [[NEGX]])306; CHECK-NEXT: ret float [[R]]307;308 %negx = fneg float %x309 %negy = fneg float %y310 %r = call float @llvm.maxnum.f32(float %negx, float %negy)311 call void @use(float %negx)312 ret float %r313}314 315define float @neg_neg_extra_use_y(float %x, float %y) {316; CHECK-LABEL: @neg_neg_extra_use_y(317; CHECK-NEXT: [[NEGY:%.*]] = fneg float [[Y:%.*]]318; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y]])319; CHECK-NEXT: [[R:%.*]] = fneg float [[TMP1]]320; CHECK-NEXT: call void @use(float [[NEGY]])321; CHECK-NEXT: ret float [[R]]322;323 %negx = fsub float -0.0, %x324 %negy = fsub float -0.0, %y325 %r = call float @llvm.maxnum.f32(float %negx, float %negy)326 call void @use(float %negy)327 ret float %r328}329 330define float @unary_neg_neg_extra_use_y(float %x, float %y) {331; CHECK-LABEL: @unary_neg_neg_extra_use_y(332; CHECK-NEXT: [[NEGY:%.*]] = fneg float [[Y:%.*]]333; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y]])334; CHECK-NEXT: [[R:%.*]] = fneg float [[TMP1]]335; CHECK-NEXT: call void @use(float [[NEGY]])336; CHECK-NEXT: ret float [[R]]337;338 %negx = fneg float %x339 %negy = fneg float %y340 %r = call float @llvm.maxnum.f32(float %negx, float %negy)341 call void @use(float %negy)342 ret float %r343}344 345define float @neg_neg_extra_use_x_and_y(float %x, float %y) {346; CHECK-LABEL: @neg_neg_extra_use_x_and_y(347; CHECK-NEXT: [[NEGX:%.*]] = fneg float [[X:%.*]]348; CHECK-NEXT: [[NEGY:%.*]] = fneg float [[Y:%.*]]349; CHECK-NEXT: [[R:%.*]] = call float @llvm.maxnum.f32(float [[NEGX]], float [[NEGY]])350; CHECK-NEXT: call void @use(float [[NEGX]])351; CHECK-NEXT: call void @use(float [[NEGY]])352; CHECK-NEXT: ret float [[R]]353;354 %negx = fsub float -0.0, %x355 %negy = fsub float -0.0, %y356 %r = call float @llvm.maxnum.f32(float %negx, float %negy)357 call void @use(float %negx)358 call void @use(float %negy)359 ret float %r360}361 362define float @unary_neg_neg_extra_use_x_and_y(float %x, float %y) {363; CHECK-LABEL: @unary_neg_neg_extra_use_x_and_y(364; CHECK-NEXT: [[NEGX:%.*]] = fneg float [[X:%.*]]365; CHECK-NEXT: [[NEGY:%.*]] = fneg float [[Y:%.*]]366; CHECK-NEXT: [[R:%.*]] = call float @llvm.maxnum.f32(float [[NEGX]], float [[NEGY]])367; CHECK-NEXT: call void @use(float [[NEGX]])368; CHECK-NEXT: call void @use(float [[NEGY]])369; CHECK-NEXT: ret float [[R]]370;371 %negx = fneg float %x372 %negy = fneg float %y373 %r = call float @llvm.maxnum.f32(float %negx, float %negy)374 call void @use(float %negx)375 call void @use(float %negy)376 ret float %r377}378 379define float @reduce_precision(float %x, float %y) {380; CHECK-LABEL: @reduce_precision(381; CHECK-NEXT: [[MAXNUM1:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])382; CHECK-NEXT: ret float [[MAXNUM1]]383;384 %x.ext = fpext float %x to double385 %y.ext = fpext float %y to double386 %maxnum = call double @llvm.maxnum.f64(double %x.ext, double %y.ext)387 %trunc = fptrunc double %maxnum to float388 ret float %trunc389}390 391define float @reduce_precision_fmf(float %x, float %y) {392; CHECK-LABEL: @reduce_precision_fmf(393; CHECK-NEXT: [[MAXNUM1:%.*]] = call nnan float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])394; CHECK-NEXT: ret float [[MAXNUM1]]395;396 %x.ext = fpext float %x to double397 %y.ext = fpext float %y to double398 %maxnum = call nnan double @llvm.maxnum.f64(double %x.ext, double %y.ext)399 %trunc = fptrunc double %maxnum to float400 ret float %trunc401}402 403define float @reduce_precision_multi_use_0(float %x, float %y, ptr %p) {404; CHECK-LABEL: @reduce_precision_multi_use_0(405; CHECK-NEXT: [[X_EXT:%.*]] = fpext float [[X:%.*]] to double406; CHECK-NEXT: [[Y_EXT:%.*]] = fpext float [[Y:%.*]] to double407; CHECK-NEXT: store double [[X_EXT]], ptr [[P:%.*]], align 8408; CHECK-NEXT: [[MAXNUM:%.*]] = call double @llvm.maxnum.f64(double [[X_EXT]], double [[Y_EXT]])409; CHECK-NEXT: [[TRUNC:%.*]] = fptrunc double [[MAXNUM]] to float410; CHECK-NEXT: ret float [[TRUNC]]411;412 %x.ext = fpext float %x to double413 %y.ext = fpext float %y to double414 store double %x.ext, ptr %p415 %maxnum = call double @llvm.maxnum.f64(double %x.ext, double %y.ext)416 %trunc = fptrunc double %maxnum to float417 ret float %trunc418}419 420define float @reduce_precision_multi_use_1(float %x, float %y, ptr %p) {421; CHECK-LABEL: @reduce_precision_multi_use_1(422; CHECK-NEXT: [[X_EXT:%.*]] = fpext float [[X:%.*]] to double423; CHECK-NEXT: [[Y_EXT:%.*]] = fpext float [[Y:%.*]] to double424; CHECK-NEXT: store double [[Y_EXT]], ptr [[P:%.*]], align 8425; CHECK-NEXT: [[MAXNUM:%.*]] = call double @llvm.maxnum.f64(double [[X_EXT]], double [[Y_EXT]])426; CHECK-NEXT: [[TRUNC:%.*]] = fptrunc double [[MAXNUM]] to float427; CHECK-NEXT: ret float [[TRUNC]]428;429 %x.ext = fpext float %x to double430 %y.ext = fpext float %y to double431 store double %y.ext, ptr %p432 %maxnum = call double @llvm.maxnum.f64(double %x.ext, double %y.ext)433 %trunc = fptrunc double %maxnum to float434 ret float %trunc435}436 437define float @negated_op(float %x) {438; CHECK-LABEL: @negated_op(439; CHECK-NEXT: [[R:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])440; CHECK-NEXT: ret float [[R]]441;442 %negx = fneg float %x443 %r = call float @llvm.maxnum.f32(float %negx, float %x)444 ret float %r445}446 447define <2 x double> @negated_op_fmf_commute_vec(<2 x double> %x) {448; CHECK-LABEL: @negated_op_fmf_commute_vec(449; CHECK-NEXT: [[R:%.*]] = call nnan ninf nsz <2 x double> @llvm.fabs.v2f64(<2 x double> [[X:%.*]])450; CHECK-NEXT: ret <2 x double> [[R]]451;452 %negx = fneg <2 x double> %x453 %r = call nsz nnan ninf <2 x double> @llvm.maxnum.v2f64(<2 x double> %x, <2 x double> %negx)454 ret <2 x double> %r455}456 457define float @negated_op_extra_use(float %x) {458; CHECK-LABEL: @negated_op_extra_use(459; CHECK-NEXT: [[NEGX:%.*]] = fneg float [[X:%.*]]460; CHECK-NEXT: call void @use(float [[NEGX]])461; CHECK-NEXT: [[R:%.*]] = call float @llvm.fabs.f32(float [[X]])462; CHECK-NEXT: ret float [[R]]463;464 %negx = fneg float %x465 call void @use(float %negx)466 %r = call float @llvm.maxnum.f32(float %negx, float %x)467 ret float %r468}469 470define float @negated_op_extra_use_comm(float %x) {471; CHECK-LABEL: @negated_op_extra_use_comm(472; CHECK-NEXT: [[NEGX:%.*]] = fneg float [[X:%.*]]473; CHECK-NEXT: call void @use(float [[NEGX]])474; CHECK-NEXT: [[R:%.*]] = call float @llvm.fabs.f32(float [[X]])475; CHECK-NEXT: ret float [[R]]476;477 %negx = fneg float %x478 call void @use(float %negx)479 %r = call float @llvm.maxnum.f32(float %x, float %negx)480 ret float %r481}482