460 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.maximum.f32(float, float)5declare <2 x float> @llvm.maximum.v2f32(<2 x float>, <2 x float>)6declare <4 x float> @llvm.maximum.v4f32(<4 x float>, <4 x float>)7 8declare double @llvm.maximum.f64(double, double)9declare <2 x double> @llvm.maximum.v2f64(<2 x double>, <2 x double>)10 11define float @constant_fold_maximum_f32() {12; CHECK-LABEL: @constant_fold_maximum_f32(13; CHECK-NEXT: ret float 2.000000e+0014;15 %x = call float @llvm.maximum.f32(float 1.0, float 2.0)16 ret float %x17}18 19define float @constant_fold_maximum_f32_inv() {20; CHECK-LABEL: @constant_fold_maximum_f32_inv(21; CHECK-NEXT: ret float 2.000000e+0022;23 %x = call float @llvm.maximum.f32(float 2.0, float 1.0)24 ret float %x25}26 27define float @constant_fold_maximum_f32_nan0() {28; CHECK-LABEL: @constant_fold_maximum_f32_nan0(29; CHECK-NEXT: ret float 0x7FF800000000000030;31 %x = call float @llvm.maximum.f32(float 0x7FF8000000000000, float 2.0)32 ret float %x33}34 35define float @constant_fold_maximum_f32_nan1() {36; CHECK-LABEL: @constant_fold_maximum_f32_nan1(37; CHECK-NEXT: ret float 0x7FF800000000000038;39 %x = call float @llvm.maximum.f32(float 2.0, float 0x7FF8000000000000)40 ret float %x41}42 43define float @constant_fold_maximum_f32_nan_nan() {44; CHECK-LABEL: @constant_fold_maximum_f32_nan_nan(45; CHECK-NEXT: ret float 0x7FF800000000000046;47 %x = call float @llvm.maximum.f32(float 0x7FF8000000000000, float 0x7FF8000000000000)48 ret float %x49}50 51define float @constant_fold_maximum_f32_p0_p0() {52; CHECK-LABEL: @constant_fold_maximum_f32_p0_p0(53; CHECK-NEXT: ret float 0.000000e+0054;55 %x = call float @llvm.maximum.f32(float 0.0, float 0.0)56 ret float %x57}58 59define float @constant_fold_maximum_f32_p0_n0() {60; CHECK-LABEL: @constant_fold_maximum_f32_p0_n0(61; CHECK-NEXT: ret float 0.000000e+0062;63 %x = call float @llvm.maximum.f32(float 0.0, float -0.0)64 ret float %x65}66 67define float @constant_fold_maximum_f32_n0_p0() {68; CHECK-LABEL: @constant_fold_maximum_f32_n0_p0(69; CHECK-NEXT: ret float 0.000000e+0070;71 %x = call float @llvm.maximum.f32(float -0.0, float 0.0)72 ret float %x73}74 75define float @constant_fold_maximum_f32_n0_n0() {76; CHECK-LABEL: @constant_fold_maximum_f32_n0_n0(77; CHECK-NEXT: ret float -0.000000e+0078;79 %x = call float @llvm.maximum.f32(float -0.0, float -0.0)80 ret float %x81}82 83define <4 x float> @constant_fold_maximum_v4f32() {84; CHECK-LABEL: @constant_fold_maximum_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.maximum.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_maximum_f64() {92; CHECK-LABEL: @constant_fold_maximum_f64(93; CHECK-NEXT: ret double 2.000000e+0094;95 %x = call double @llvm.maximum.f64(double 1.0, double 2.0)96 ret double %x97}98 99define double @constant_fold_maximum_f64_nan0() {100; CHECK-LABEL: @constant_fold_maximum_f64_nan0(101; CHECK-NEXT: ret double 0x7FF8000000000000102;103 %x = call double @llvm.maximum.f64(double 0x7FF8000000000000, double 2.0)104 ret double %x105}106 107define double @constant_fold_maximum_f64_nan1() {108; CHECK-LABEL: @constant_fold_maximum_f64_nan1(109; CHECK-NEXT: ret double 0x7FF8000000000000110;111 %x = call double @llvm.maximum.f64(double 2.0, double 0x7FF8000000000000)112 ret double %x113}114 115define double @constant_fold_maximum_f64_nan_nan() {116; CHECK-LABEL: @constant_fold_maximum_f64_nan_nan(117; CHECK-NEXT: ret double 0x7FF8000000000000118;119 %x = call double @llvm.maximum.f64(double 0x7FF8000000000000, double 0x7FF8000000000000)120 ret double %x121}122 123define float @canonicalize_constant_maximum_f32(float %x) {124; CHECK-LABEL: @canonicalize_constant_maximum_f32(125; CHECK-NEXT: [[Y:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float 1.000000e+00)126; CHECK-NEXT: ret float [[Y]]127;128 %y = call float @llvm.maximum.f32(float 1.0, float %x)129 ret float %y130}131 132define float @maximum_f32_nan_val(float %x) {133; CHECK-LABEL: @maximum_f32_nan_val(134; CHECK-NEXT: ret float 0x7FF8000000000000135;136 %y = call float @llvm.maximum.f32(float 0x7FF8000000000000, float %x)137 ret float %y138}139 140define float @maximum_f32_val_nan(float %x) {141; CHECK-LABEL: @maximum_f32_val_nan(142; CHECK-NEXT: ret float 0x7FF8000000000000143;144 %y = call float @llvm.maximum.f32(float %x, float 0x7FF8000000000000)145 ret float %y146}147 148define float @maximum_f32_1_maximum_val_p0(float %x) {149; CHECK-LABEL: @maximum_f32_1_maximum_val_p0(150; CHECK-NEXT: [[Z:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float 1.000000e+00)151; CHECK-NEXT: ret float [[Z]]152;153 %y = call float @llvm.maximum.f32(float %x, float 0.0)154 %z = call float @llvm.maximum.f32(float %y, float 1.0)155 ret float %z156}157 158define float @maximum_f32_1_maximum_p0_val_fast(float %x) {159; CHECK-LABEL: @maximum_f32_1_maximum_p0_val_fast(160; CHECK-NEXT: [[Z:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float 1.000000e+00)161; CHECK-NEXT: ret float [[Z]]162;163 %y = call float @llvm.maximum.f32(float 0.0, float %x)164 %z = call fast float @llvm.maximum.f32(float %y, float 1.0)165 ret float %z166}167 168define float @maximum_f32_1_maximum_p0_val_fmf1(float %x) {169; CHECK-LABEL: @maximum_f32_1_maximum_p0_val_fmf1(170; CHECK-NEXT: [[Z:%.*]] = call nnan arcp float @llvm.maximum.f32(float [[X:%.*]], float 1.000000e+00)171; CHECK-NEXT: ret float [[Z]]172;173 %y = call arcp nnan float @llvm.maximum.f32(float 0.0, float %x)174 %z = call arcp nnan ninf float @llvm.maximum.f32(float %y, float 1.0)175 ret float %z176}177 178define float @maximum_f32_1_maximum_p0_val_fmf2(float %x) {179; CHECK-LABEL: @maximum_f32_1_maximum_p0_val_fmf2(180; CHECK-NEXT: [[Z:%.*]] = call nnan float @llvm.maximum.f32(float [[X:%.*]], float 1.000000e+00)181; CHECK-NEXT: ret float [[Z]]182;183 %y = call arcp nnan ninf float @llvm.maximum.f32(float 0.0, float %x)184 %z = call nnan float @llvm.maximum.f32(float %y, float 1.0)185 ret float %z186}187 188define float @maximum_f32_1_maximum_p0_val_fmf3(float %x) {189; CHECK-LABEL: @maximum_f32_1_maximum_p0_val_fmf3(190; CHECK-NEXT: [[Z:%.*]] = call nnan ninf float @llvm.maximum.f32(float [[X:%.*]], float 1.000000e+00)191; CHECK-NEXT: ret float [[Z]]192;193 %y = call nnan ninf float @llvm.maximum.f32(float 0.0, float %x)194 %z = call arcp nnan ninf float @llvm.maximum.f32(float %y, float 1.0)195 ret float %z196}197 198define float @maximum_f32_p0_maximum_val_n0(float %x) {199; CHECK-LABEL: @maximum_f32_p0_maximum_val_n0(200; CHECK-NEXT: [[Z:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float 0.000000e+00)201; CHECK-NEXT: ret float [[Z]]202;203 %y = call float @llvm.maximum.f32(float %x, float -0.0)204 %z = call float @llvm.maximum.f32(float %y, float 0.0)205 ret float %z206}207 208define float @maximum_f32_1_maximum_p0_val(float %x) {209; CHECK-LABEL: @maximum_f32_1_maximum_p0_val(210; CHECK-NEXT: [[Z:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float 1.000000e+00)211; CHECK-NEXT: ret float [[Z]]212;213 %y = call float @llvm.maximum.f32(float 0.0, float %x)214 %z = call float @llvm.maximum.f32(float %y, float 1.0)215 ret float %z216}217 218define <2 x float> @maximum_f32_1_maximum_val_p0_val_v2f32(<2 x float> %x) {219; CHECK-LABEL: @maximum_f32_1_maximum_val_p0_val_v2f32(220; CHECK-NEXT: [[Z:%.*]] = call <2 x float> @llvm.maximum.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.maximum.v2f32(<2 x float> %x, <2 x float> zeroinitializer)224 %z = call <2 x float> @llvm.maximum.v2f32(<2 x float> %y, <2 x float><float 1.0, float 1.0>)225 ret <2 x float> %z226}227 228define float @maximum4(float %x, float %y, float %z, float %w) {229; CHECK-LABEL: @maximum4(230; CHECK-NEXT: [[A:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]])231; CHECK-NEXT: [[B:%.*]] = call float @llvm.maximum.f32(float [[Z:%.*]], float [[W:%.*]])232; CHECK-NEXT: [[C:%.*]] = call float @llvm.maximum.f32(float [[A]], float [[B]])233; CHECK-NEXT: ret float [[C]]234;235 %a = call float @llvm.maximum.f32(float %x, float %y)236 %b = call float @llvm.maximum.f32(float %z, float %w)237 %c = call float @llvm.maximum.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.minimum.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.maximum.v2f32(<2 x float> %negx, <2 x float> %negy)252 ret <2 x float> %r253}254 255define <2 x float> @unary_neg_neg(<2 x float> %x, <2 x float> %y) {256; CHECK-LABEL: @unary_neg_neg(257; CHECK-NEXT: [[TMP1:%.*]] = call <2 x float> @llvm.minimum.v2f32(<2 x float> [[X:%.*]], <2 x float> [[Y:%.*]])258; CHECK-NEXT: [[R:%.*]] = fneg <2 x float> [[TMP1]]259; CHECK-NEXT: ret <2 x float> [[R]]260;261 %negx = fneg <2 x float> %x262 %negy = fneg <2 x float> %y263 %r = call <2 x float> @llvm.maximum.v2f32(<2 x float> %negx, <2 x float> %negy)264 ret <2 x float> %r265}266 267; FMF is not required, but it should be propagated from the intrinsic (not the fnegs).268 269define float @neg_neg_vec_fmf(float %x, float %y) {270; CHECK-LABEL: @neg_neg_vec_fmf(271; CHECK-NEXT: [[TMP1:%.*]] = call fast float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]])272; CHECK-NEXT: [[R:%.*]] = fneg fast float [[TMP1]]273; CHECK-NEXT: ret float [[R]]274;275 %negx = fsub arcp float -0.0, %x276 %negy = fsub afn float -0.0, %y277 %r = call fast float @llvm.maximum.f32(float %negx, float %negy)278 ret float %r279}280 281define float @unary_neg_neg_vec_fmf(float %x, float %y) {282; CHECK-LABEL: @unary_neg_neg_vec_fmf(283; CHECK-NEXT: [[TMP1:%.*]] = call fast float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]])284; CHECK-NEXT: [[R:%.*]] = fneg fast float [[TMP1]]285; CHECK-NEXT: ret float [[R]]286;287 %negx = fneg arcp float %x288 %negy = fneg afn float %y289 %r = call fast float @llvm.maximum.f32(float %negx, float %negy)290 ret float %r291}292 293; 1 extra use of an intermediate value should still allow the fold,294; but 2 would require more instructions than we started with.295 296declare void @use(float)297define float @neg_neg_extra_use_x(float %x, float %y) {298; CHECK-LABEL: @neg_neg_extra_use_x(299; CHECK-NEXT: [[NEGX:%.*]] = fneg float [[X:%.*]]300; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.minimum.f32(float [[X]], float [[Y:%.*]])301; CHECK-NEXT: [[R:%.*]] = fneg float [[TMP1]]302; CHECK-NEXT: call void @use(float [[NEGX]])303; CHECK-NEXT: ret float [[R]]304;305 %negx = fsub float -0.0, %x306 %negy = fsub float -0.0, %y307 %r = call float @llvm.maximum.f32(float %negx, float %negy)308 call void @use(float %negx)309 ret float %r310}311 312define float @unary_neg_neg_extra_use_x(float %x, float %y) {313; CHECK-LABEL: @unary_neg_neg_extra_use_x(314; CHECK-NEXT: [[NEGX:%.*]] = fneg float [[X:%.*]]315; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.minimum.f32(float [[X]], float [[Y:%.*]])316; CHECK-NEXT: [[R:%.*]] = fneg float [[TMP1]]317; CHECK-NEXT: call void @use(float [[NEGX]])318; CHECK-NEXT: ret float [[R]]319;320 %negx = fneg float %x321 %negy = fneg float %y322 %r = call float @llvm.maximum.f32(float %negx, float %negy)323 call void @use(float %negx)324 ret float %r325}326 327define float @neg_neg_extra_use_y(float %x, float %y) {328; CHECK-LABEL: @neg_neg_extra_use_y(329; CHECK-NEXT: [[NEGY:%.*]] = fneg float [[Y:%.*]]330; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y]])331; CHECK-NEXT: [[R:%.*]] = fneg float [[TMP1]]332; CHECK-NEXT: call void @use(float [[NEGY]])333; CHECK-NEXT: ret float [[R]]334;335 %negx = fsub float -0.0, %x336 %negy = fsub float -0.0, %y337 %r = call float @llvm.maximum.f32(float %negx, float %negy)338 call void @use(float %negy)339 ret float %r340}341 342define float @unary_neg_neg_extra_use_y(float %x, float %y) {343; CHECK-LABEL: @unary_neg_neg_extra_use_y(344; CHECK-NEXT: [[NEGY:%.*]] = fneg float [[Y:%.*]]345; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y]])346; CHECK-NEXT: [[R:%.*]] = fneg float [[TMP1]]347; CHECK-NEXT: call void @use(float [[NEGY]])348; CHECK-NEXT: ret float [[R]]349;350 %negx = fneg float %x351 %negy = fneg float %y352 %r = call float @llvm.maximum.f32(float %negx, float %negy)353 call void @use(float %negy)354 ret float %r355}356 357define float @neg_neg_extra_use_x_and_y(float %x, float %y) {358; CHECK-LABEL: @neg_neg_extra_use_x_and_y(359; CHECK-NEXT: [[NEGX:%.*]] = fneg float [[X:%.*]]360; CHECK-NEXT: [[NEGY:%.*]] = fneg float [[Y:%.*]]361; CHECK-NEXT: [[R:%.*]] = call float @llvm.maximum.f32(float [[NEGX]], float [[NEGY]])362; CHECK-NEXT: call void @use(float [[NEGX]])363; CHECK-NEXT: call void @use(float [[NEGY]])364; CHECK-NEXT: ret float [[R]]365;366 %negx = fsub float -0.0, %x367 %negy = fsub float -0.0, %y368 %r = call float @llvm.maximum.f32(float %negx, float %negy)369 call void @use(float %negx)370 call void @use(float %negy)371 ret float %r372}373 374define float @unary_neg_neg_extra_use_x_and_y(float %x, float %y) {375; CHECK-LABEL: @unary_neg_neg_extra_use_x_and_y(376; CHECK-NEXT: [[NEGX:%.*]] = fneg float [[X:%.*]]377; CHECK-NEXT: [[NEGY:%.*]] = fneg float [[Y:%.*]]378; CHECK-NEXT: [[R:%.*]] = call float @llvm.maximum.f32(float [[NEGX]], float [[NEGY]])379; CHECK-NEXT: call void @use(float [[NEGX]])380; CHECK-NEXT: call void @use(float [[NEGY]])381; CHECK-NEXT: ret float [[R]]382;383 %negx = fneg float %x384 %negy = fneg float %y385 %r = call float @llvm.maximum.f32(float %negx, float %negy)386 call void @use(float %negx)387 call void @use(float %negy)388 ret float %r389}390 391define float @reduce_precision(float %x, float %y) {392; CHECK-LABEL: @reduce_precision(393; CHECK-NEXT: [[MAXIMUM1:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]])394; CHECK-NEXT: ret float [[MAXIMUM1]]395;396 %x.ext = fpext float %x to double397 %y.ext = fpext float %y to double398 %maximum = call double @llvm.maximum.f64(double %x.ext, double %y.ext)399 %trunc = fptrunc double %maximum to float400 ret float %trunc401}402 403define float @reduce_precision_fmf(float %x, float %y) {404; CHECK-LABEL: @reduce_precision_fmf(405; CHECK-NEXT: [[MAXIMUM1:%.*]] = call nnan float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]])406; CHECK-NEXT: ret float [[MAXIMUM1]]407;408 %x.ext = fpext float %x to double409 %y.ext = fpext float %y to double410 %maximum = call nnan double @llvm.maximum.f64(double %x.ext, double %y.ext)411 %trunc = fptrunc double %maximum to float412 ret float %trunc413}414 415define float @negated_op(float %x) {416; CHECK-LABEL: @negated_op(417; CHECK-NEXT: [[R:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])418; CHECK-NEXT: ret float [[R]]419;420 %negx = fneg float %x421 %r = call float @llvm.maximum.f32(float %x, float %negx)422 ret float %r423}424 425define <2 x double> @negated_op_fmf_commute_vec(<2 x double> %x) {426; CHECK-LABEL: @negated_op_fmf_commute_vec(427; CHECK-NEXT: [[R:%.*]] = call nnan ninf nsz <2 x double> @llvm.fabs.v2f64(<2 x double> [[X:%.*]])428; CHECK-NEXT: ret <2 x double> [[R]]429;430 %negx = fneg <2 x double> %x431 %r = call nsz nnan ninf <2 x double> @llvm.maximum.v2f64(<2 x double> %negx, <2 x double> %x)432 ret <2 x double> %r433}434 435define float @negated_op_extra_use(float %x) {436; CHECK-LABEL: @negated_op_extra_use(437; CHECK-NEXT: [[NEGX:%.*]] = fneg float [[X:%.*]]438; CHECK-NEXT: call void @use(float [[NEGX]])439; CHECK-NEXT: [[R:%.*]] = call float @llvm.fabs.f32(float [[X]])440; CHECK-NEXT: ret float [[R]]441;442 %negx = fneg float %x443 call void @use(float %negx)444 %r = call float @llvm.maximum.f32(float %negx, float %x)445 ret float %r446}447 448define float @negated_op_extra_use_comm(float %x) {449; CHECK-LABEL: @negated_op_extra_use_comm(450; CHECK-NEXT: [[NEGX:%.*]] = fneg float [[X:%.*]]451; CHECK-NEXT: call void @use(float [[NEGX]])452; CHECK-NEXT: [[R:%.*]] = call float @llvm.fabs.f32(float [[X]])453; CHECK-NEXT: ret float [[R]]454;455 %negx = fneg float %x456 call void @use(float %negx)457 %r = call float @llvm.maximum.f32(float %x, float %negx)458 ret float %r459}460