1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -instcombine < %s | FileCheck %s 3 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+00 14; 15 %x = call float @llvm.maxnum.f32(float 1.0, float 2.0) 16 ret float %x 17} 18 19define float @constant_fold_maxnum_f32_inv() { 20; CHECK-LABEL: @constant_fold_maxnum_f32_inv( 21; CHECK-NEXT: ret float 2.000000e+00 22; 23 %x = call float @llvm.maxnum.f32(float 2.0, float 1.0) 24 ret float %x 25} 26 27define float @constant_fold_maxnum_f32_nan0() { 28; CHECK-LABEL: @constant_fold_maxnum_f32_nan0( 29; CHECK-NEXT: ret float 2.000000e+00 30; 31 %x = call float @llvm.maxnum.f32(float 0x7FF8000000000000, float 2.0) 32 ret float %x 33} 34 35define float @constant_fold_maxnum_f32_nan1() { 36; CHECK-LABEL: @constant_fold_maxnum_f32_nan1( 37; CHECK-NEXT: ret float 2.000000e+00 38; 39 %x = call float @llvm.maxnum.f32(float 2.0, float 0x7FF8000000000000) 40 ret float %x 41} 42 43define float @constant_fold_maxnum_f32_nan_nan() { 44; CHECK-LABEL: @constant_fold_maxnum_f32_nan_nan( 45; CHECK-NEXT: ret float 0x7FF8000000000000 46; 47 %x = call float @llvm.maxnum.f32(float 0x7FF8000000000000, float 0x7FF8000000000000) 48 ret float %x 49} 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+00 54; 55 %x = call float @llvm.maxnum.f32(float 0.0, float 0.0) 56 ret float %x 57} 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+00 62; 63 %x = call float @llvm.maxnum.f32(float 0.0, float -0.0) 64 ret float %x 65} 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+00 70; 71 %x = call float @llvm.maxnum.f32(float -0.0, float 0.0) 72 ret float %x 73} 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+00 78; 79 %x = call float @llvm.maxnum.f32(float -0.0, float -0.0) 80 ret float %x 81} 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> %x 89} 90 91define double @constant_fold_maxnum_f64() { 92; CHECK-LABEL: @constant_fold_maxnum_f64( 93; CHECK-NEXT: ret double 2.000000e+00 94; 95 %x = call double @llvm.maxnum.f64(double 1.0, double 2.0) 96 ret double %x 97} 98 99define double @constant_fold_maxnum_f64_nan0() { 100; CHECK-LABEL: @constant_fold_maxnum_f64_nan0( 101; CHECK-NEXT: ret double 2.000000e+00 102; 103 %x = call double @llvm.maxnum.f64(double 0x7FF8000000000000, double 2.0) 104 ret double %x 105} 106 107define double @constant_fold_maxnum_f64_nan1() { 108; CHECK-LABEL: @constant_fold_maxnum_f64_nan1( 109; CHECK-NEXT: ret double 2.000000e+00 110; 111 %x = call double @llvm.maxnum.f64(double 2.0, double 0x7FF8000000000000) 112 ret double %x 113} 114 115define double @constant_fold_maxnum_f64_nan_nan() { 116; CHECK-LABEL: @constant_fold_maxnum_f64_nan_nan( 117; CHECK-NEXT: ret double 0x7FF8000000000000 118; 119 %x = call double @llvm.maxnum.f64(double 0x7FF8000000000000, double 0x7FF8000000000000) 120 ret double %x 121} 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 %y 130} 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 %y 138} 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 %y 146} 147 148define float @maxnum_f32_1_maxnum_val_p0(float %x) { 149; CHECK-LABEL: @maxnum_f32_1_maxnum_val_p0( 150; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float 1.000000e+00) 151; CHECK-NEXT: ret float [[TMP1]] 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 %z 156} 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: [[TMP1:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float 1.000000e+00) 161; CHECK-NEXT: ret float [[TMP1]] 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 %z 166} 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: [[TMP1:%.*]] = call nnan float @llvm.maxnum.f32(float [[X:%.*]], float 1.000000e+00) 171; CHECK-NEXT: ret float [[TMP1]] 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 %z 176} 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: [[TMP1:%.*]] = call ninf float @llvm.maxnum.f32(float [[X:%.*]], float 1.000000e+00) 181; CHECK-NEXT: ret float [[TMP1]] 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 %z 186} 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: [[TMP1:%.*]] = call nnan ninf float @llvm.maxnum.f32(float [[X:%.*]], float 1.000000e+00) 191; CHECK-NEXT: ret float [[TMP1]] 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 %z 196} 197 198define float @maxnum_f32_p0_maxnum_val_n0(float %x) { 199; CHECK-LABEL: @maxnum_f32_p0_maxnum_val_n0( 200; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float 0.000000e+00) 201; CHECK-NEXT: ret float [[TMP1]] 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 %z 206} 207 208define float @maxnum_f32_1_maxnum_p0_val(float %x) { 209; CHECK-LABEL: @maxnum_f32_1_maxnum_p0_val( 210; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float 1.000000e+00) 211; CHECK-NEXT: ret float [[TMP1]] 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 %z 216} 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: [[TMP1:%.*]] = call <2 x float> @llvm.maxnum.v2f32(<2 x float> [[X:%.*]], <2 x float> <float 1.000000e+00, float 1.000000e+00>) 221; CHECK-NEXT: ret <2 x float> [[TMP1]] 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> %z 226} 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 %c 239} 240 241; PR37404 - https://bugs.llvm.org/show_bug.cgi?id=37404 242 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>, %x 250 %negy = fsub <2 x float> <float -0.0, float -0.0>, %y 251 %r = call <2 x float> @llvm.maxnum.v2f32(<2 x float> %negx, <2 x float> %negy) 252 ret <2 x float> %r 253} 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, %x 264 %negy = fsub afn float -0.0, %y 265 %r = call fast float @llvm.maxnum.f32(float %negx, float %negy) 266 ret float %r 267} 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 %x 276 %negy = fneg afn float %y 277 %r = call fast float @llvm.maxnum.f32(float %negx, float %negy) 278 ret float %r 279} 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, %x 294 %negy = fsub float -0.0, %y 295 %r = call float @llvm.maxnum.f32(float %negx, float %negy) 296 call void @use(float %negx) 297 ret float %r 298} 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 %x 309 %negy = fneg float %y 310 %r = call float @llvm.maxnum.f32(float %negx, float %negy) 311 call void @use(float %negx) 312 ret float %r 313} 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, %x 324 %negy = fsub float -0.0, %y 325 %r = call float @llvm.maxnum.f32(float %negx, float %negy) 326 call void @use(float %negy) 327 ret float %r 328} 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 %x 339 %negy = fneg float %y 340 %r = call float @llvm.maxnum.f32(float %negx, float %negy) 341 call void @use(float %negy) 342 ret float %r 343} 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, %x 355 %negy = fsub float -0.0, %y 356 %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 %r 360} 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 %x 372 %negy = fneg float %y 373 %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 %r 377} 378 379define float @reduce_precision(float %x, float %y) { 380; CHECK-LABEL: @reduce_precision( 381; CHECK-NEXT: [[MAXNUM:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]]) 382; CHECK-NEXT: ret float [[MAXNUM]] 383; 384 %x.ext = fpext float %x to double 385 %y.ext = fpext float %y to double 386 %maxnum = call double @llvm.maxnum.f64(double %x.ext, double %y.ext) 387 %trunc = fptrunc double %maxnum to float 388 ret float %trunc 389} 390 391define float @reduce_precision_fmf(float %x, float %y) { 392; CHECK-LABEL: @reduce_precision_fmf( 393; CHECK-NEXT: [[MAXNUM:%.*]] = call nnan float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]]) 394; CHECK-NEXT: ret float [[MAXNUM]] 395; 396 %x.ext = fpext float %x to double 397 %y.ext = fpext float %y to double 398 %maxnum = call nnan double @llvm.maxnum.f64(double %x.ext, double %y.ext) 399 %trunc = fptrunc double %maxnum to float 400 ret float %trunc 401} 402 403define float @reduce_precision_multi_use_0(float %x, float %y) { 404; CHECK-LABEL: @reduce_precision_multi_use_0( 405; CHECK-NEXT: [[X_EXT:%.*]] = fpext float [[X:%.*]] to double 406; CHECK-NEXT: [[Y_EXT:%.*]] = fpext float [[Y:%.*]] to double 407; CHECK-NEXT: store double [[X_EXT]], double* undef, align 8 408; CHECK-NEXT: [[MAXNUM:%.*]] = call double @llvm.maxnum.f64(double [[X_EXT]], double [[Y_EXT]]) 409; CHECK-NEXT: [[TRUNC:%.*]] = fptrunc double [[MAXNUM]] to float 410; CHECK-NEXT: ret float [[TRUNC]] 411; 412 %x.ext = fpext float %x to double 413 %y.ext = fpext float %y to double 414 store double %x.ext, double* undef 415 %maxnum = call double @llvm.maxnum.f64(double %x.ext, double %y.ext) 416 %trunc = fptrunc double %maxnum to float 417 ret float %trunc 418} 419 420define float @reduce_precision_multi_use_1(float %x, float %y) { 421; CHECK-LABEL: @reduce_precision_multi_use_1( 422; CHECK-NEXT: [[X_EXT:%.*]] = fpext float [[X:%.*]] to double 423; CHECK-NEXT: [[Y_EXT:%.*]] = fpext float [[Y:%.*]] to double 424; CHECK-NEXT: store double [[Y_EXT]], double* undef, align 8 425; CHECK-NEXT: [[MAXNUM:%.*]] = call double @llvm.maxnum.f64(double [[X_EXT]], double [[Y_EXT]]) 426; CHECK-NEXT: [[TRUNC:%.*]] = fptrunc double [[MAXNUM]] to float 427; CHECK-NEXT: ret float [[TRUNC]] 428; 429 %x.ext = fpext float %x to double 430 %y.ext = fpext float %y to double 431 store double %y.ext, double* undef 432 %maxnum = call double @llvm.maxnum.f64(double %x.ext, double %y.ext) 433 %trunc = fptrunc double %maxnum to float 434 ret float %trunc 435} 436