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 fast 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 @maxnum_f32_1_maxnum_p0_val_nnan_ninf(float %x) { 169; CHECK-LABEL: @maxnum_f32_1_maxnum_p0_val_nnan_ninf( 170; CHECK-NEXT: [[TMP1:%.*]] = call nnan ninf float @llvm.maxnum.f32(float [[X:%.*]], float 1.000000e+00) 171; CHECK-NEXT: ret float [[TMP1]] 172; 173 %y = call 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 @maxnum_f32_p0_maxnum_val_n0(float %x) { 179; CHECK-LABEL: @maxnum_f32_p0_maxnum_val_n0( 180; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float 0.000000e+00) 181; CHECK-NEXT: ret float [[TMP1]] 182; 183 %y = call float @llvm.maxnum.f32(float %x, float -0.0) 184 %z = call float @llvm.maxnum.f32(float %y, float 0.0) 185 ret float %z 186} 187 188define float @maxnum_f32_1_maxnum_p0_val(float %x) { 189; CHECK-LABEL: @maxnum_f32_1_maxnum_p0_val( 190; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float 1.000000e+00) 191; CHECK-NEXT: ret float [[TMP1]] 192; 193 %y = call float @llvm.maxnum.f32(float 0.0, float %x) 194 %z = call float @llvm.maxnum.f32(float %y, float 1.0) 195 ret float %z 196} 197 198define <2 x float> @maxnum_f32_1_maxnum_val_p0_val_v2f32(<2 x float> %x) { 199; CHECK-LABEL: @maxnum_f32_1_maxnum_val_p0_val_v2f32( 200; 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>) 201; CHECK-NEXT: ret <2 x float> [[TMP1]] 202; 203 %y = call <2 x float> @llvm.maxnum.v2f32(<2 x float> %x, <2 x float> zeroinitializer) 204 %z = call <2 x float> @llvm.maxnum.v2f32(<2 x float> %y, <2 x float><float 1.0, float 1.0>) 205 ret <2 x float> %z 206} 207 208define float @maxnum4(float %x, float %y, float %z, float %w) { 209; CHECK-LABEL: @maxnum4( 210; CHECK-NEXT: [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]]) 211; CHECK-NEXT: [[B:%.*]] = call float @llvm.maxnum.f32(float [[Z:%.*]], float [[W:%.*]]) 212; CHECK-NEXT: [[C:%.*]] = call float @llvm.maxnum.f32(float [[A]], float [[B]]) 213; CHECK-NEXT: ret float [[C]] 214; 215 %a = call float @llvm.maxnum.f32(float %x, float %y) 216 %b = call float @llvm.maxnum.f32(float %z, float %w) 217 %c = call float @llvm.maxnum.f32(float %a, float %b) 218 ret float %c 219} 220 221; PR37404 - https://bugs.llvm.org/show_bug.cgi?id=37404 222 223define <2 x float> @neg_neg(<2 x float> %x, <2 x float> %y) { 224; CHECK-LABEL: @neg_neg( 225; CHECK-NEXT: [[TMP1:%.*]] = call <2 x float> @llvm.minnum.v2f32(<2 x float> [[X:%.*]], <2 x float> [[Y:%.*]]) 226; CHECK-NEXT: [[R:%.*]] = fneg <2 x float> [[TMP1]] 227; CHECK-NEXT: ret <2 x float> [[R]] 228; 229 %negx = fsub <2 x float> <float -0.0, float -0.0>, %x 230 %negy = fsub <2 x float> <float -0.0, float -0.0>, %y 231 %r = call <2 x float> @llvm.maxnum.v2f32(<2 x float> %negx, <2 x float> %negy) 232 ret <2 x float> %r 233} 234 235; FMF is not required, but it should be propagated from the intrinsic (not the fnegs). 236 237define float @neg_neg_vec_fmf(float %x, float %y) { 238; CHECK-LABEL: @neg_neg_vec_fmf( 239; CHECK-NEXT: [[TMP1:%.*]] = call fast float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]]) 240; CHECK-NEXT: [[R:%.*]] = fneg fast float [[TMP1]] 241; CHECK-NEXT: ret float [[R]] 242; 243 %negx = fsub arcp float -0.0, %x 244 %negy = fsub afn float -0.0, %y 245 %r = call fast float @llvm.maxnum.f32(float %negx, float %negy) 246 ret float %r 247} 248 249define float @unary_neg_neg_vec_fmf(float %x, float %y) { 250; CHECK-LABEL: @unary_neg_neg_vec_fmf( 251; CHECK-NEXT: [[TMP1:%.*]] = call fast float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]]) 252; CHECK-NEXT: [[R:%.*]] = fneg fast float [[TMP1]] 253; CHECK-NEXT: ret float [[R]] 254; 255 %negx = fneg arcp float %x 256 %negy = fneg afn float %y 257 %r = call fast float @llvm.maxnum.f32(float %negx, float %negy) 258 ret float %r 259} 260 261; 1 extra use of an intermediate value should still allow the fold, 262; but 2 would require more instructions than we started with. 263 264declare void @use(float) 265define float @neg_neg_extra_use_x(float %x, float %y) { 266; CHECK-LABEL: @neg_neg_extra_use_x( 267; CHECK-NEXT: [[NEGX:%.*]] = fneg float [[X:%.*]] 268; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.minnum.f32(float [[X]], float [[Y:%.*]]) 269; CHECK-NEXT: [[R:%.*]] = fneg float [[TMP1]] 270; CHECK-NEXT: call void @use(float [[NEGX]]) 271; CHECK-NEXT: ret float [[R]] 272; 273 %negx = fsub float -0.0, %x 274 %negy = fsub float -0.0, %y 275 %r = call float @llvm.maxnum.f32(float %negx, float %negy) 276 call void @use(float %negx) 277 ret float %r 278} 279 280define float @unary_neg_neg_extra_use_x(float %x, float %y) { 281; CHECK-LABEL: @unary_neg_neg_extra_use_x( 282; CHECK-NEXT: [[NEGX:%.*]] = fneg float [[X:%.*]] 283; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.minnum.f32(float [[X]], float [[Y:%.*]]) 284; CHECK-NEXT: [[R:%.*]] = fneg float [[TMP1]] 285; CHECK-NEXT: call void @use(float [[NEGX]]) 286; CHECK-NEXT: ret float [[R]] 287; 288 %negx = fneg float %x 289 %negy = fneg float %y 290 %r = call float @llvm.maxnum.f32(float %negx, float %negy) 291 call void @use(float %negx) 292 ret float %r 293} 294 295define float @neg_neg_extra_use_y(float %x, float %y) { 296; CHECK-LABEL: @neg_neg_extra_use_y( 297; CHECK-NEXT: [[NEGY:%.*]] = fneg float [[Y:%.*]] 298; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y]]) 299; CHECK-NEXT: [[R:%.*]] = fneg float [[TMP1]] 300; CHECK-NEXT: call void @use(float [[NEGY]]) 301; CHECK-NEXT: ret float [[R]] 302; 303 %negx = fsub float -0.0, %x 304 %negy = fsub float -0.0, %y 305 %r = call float @llvm.maxnum.f32(float %negx, float %negy) 306 call void @use(float %negy) 307 ret float %r 308} 309 310define float @unary_neg_neg_extra_use_y(float %x, float %y) { 311; CHECK-LABEL: @unary_neg_neg_extra_use_y( 312; CHECK-NEXT: [[NEGY:%.*]] = fneg float [[Y:%.*]] 313; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y]]) 314; CHECK-NEXT: [[R:%.*]] = fneg float [[TMP1]] 315; CHECK-NEXT: call void @use(float [[NEGY]]) 316; CHECK-NEXT: ret float [[R]] 317; 318 %negx = fneg float %x 319 %negy = fneg float %y 320 %r = call float @llvm.maxnum.f32(float %negx, float %negy) 321 call void @use(float %negy) 322 ret float %r 323} 324 325define float @neg_neg_extra_use_x_and_y(float %x, float %y) { 326; CHECK-LABEL: @neg_neg_extra_use_x_and_y( 327; CHECK-NEXT: [[NEGX:%.*]] = fneg float [[X:%.*]] 328; CHECK-NEXT: [[NEGY:%.*]] = fneg float [[Y:%.*]] 329; CHECK-NEXT: [[R:%.*]] = call float @llvm.maxnum.f32(float [[NEGX]], float [[NEGY]]) 330; CHECK-NEXT: call void @use(float [[NEGX]]) 331; CHECK-NEXT: call void @use(float [[NEGY]]) 332; CHECK-NEXT: ret float [[R]] 333; 334 %negx = fsub float -0.0, %x 335 %negy = fsub float -0.0, %y 336 %r = call float @llvm.maxnum.f32(float %negx, float %negy) 337 call void @use(float %negx) 338 call void @use(float %negy) 339 ret float %r 340} 341 342define float @unary_neg_neg_extra_use_x_and_y(float %x, float %y) { 343; CHECK-LABEL: @unary_neg_neg_extra_use_x_and_y( 344; CHECK-NEXT: [[NEGX:%.*]] = fneg float [[X:%.*]] 345; CHECK-NEXT: [[NEGY:%.*]] = fneg float [[Y:%.*]] 346; CHECK-NEXT: [[R:%.*]] = call float @llvm.maxnum.f32(float [[NEGX]], float [[NEGY]]) 347; CHECK-NEXT: call void @use(float [[NEGX]]) 348; CHECK-NEXT: call void @use(float [[NEGY]]) 349; CHECK-NEXT: ret float [[R]] 350; 351 %negx = fneg float %x 352 %negy = fneg float %y 353 %r = call float @llvm.maxnum.f32(float %negx, float %negy) 354 call void @use(float %negx) 355 call void @use(float %negy) 356 ret float %r 357} 358 359define float @reduce_precision(float %x, float %y) { 360; CHECK-LABEL: @reduce_precision( 361; CHECK-NEXT: [[MAXNUM:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]]) 362; CHECK-NEXT: ret float [[MAXNUM]] 363; 364 %x.ext = fpext float %x to double 365 %y.ext = fpext float %y to double 366 %maxnum = call double @llvm.maxnum.f64(double %x.ext, double %y.ext) 367 %trunc = fptrunc double %maxnum to float 368 ret float %trunc 369} 370 371define float @reduce_precision_fmf(float %x, float %y) { 372; CHECK-LABEL: @reduce_precision_fmf( 373; CHECK-NEXT: [[MAXNUM:%.*]] = call nnan float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]]) 374; CHECK-NEXT: ret float [[MAXNUM]] 375; 376 %x.ext = fpext float %x to double 377 %y.ext = fpext float %y to double 378 %maxnum = call nnan double @llvm.maxnum.f64(double %x.ext, double %y.ext) 379 %trunc = fptrunc double %maxnum to float 380 ret float %trunc 381} 382 383define float @reduce_precision_multi_use_0(float %x, float %y) { 384; CHECK-LABEL: @reduce_precision_multi_use_0( 385; CHECK-NEXT: [[X_EXT:%.*]] = fpext float [[X:%.*]] to double 386; CHECK-NEXT: [[Y_EXT:%.*]] = fpext float [[Y:%.*]] to double 387; CHECK-NEXT: store double [[X_EXT]], double* undef, align 8 388; CHECK-NEXT: [[MAXNUM:%.*]] = call double @llvm.maxnum.f64(double [[X_EXT]], double [[Y_EXT]]) 389; CHECK-NEXT: [[TRUNC:%.*]] = fptrunc double [[MAXNUM]] to float 390; CHECK-NEXT: ret float [[TRUNC]] 391; 392 %x.ext = fpext float %x to double 393 %y.ext = fpext float %y to double 394 store double %x.ext, double* undef 395 %maxnum = call double @llvm.maxnum.f64(double %x.ext, double %y.ext) 396 %trunc = fptrunc double %maxnum to float 397 ret float %trunc 398} 399 400define float @reduce_precision_multi_use_1(float %x, float %y) { 401; CHECK-LABEL: @reduce_precision_multi_use_1( 402; CHECK-NEXT: [[X_EXT:%.*]] = fpext float [[X:%.*]] to double 403; CHECK-NEXT: [[Y_EXT:%.*]] = fpext float [[Y:%.*]] to double 404; CHECK-NEXT: store double [[Y_EXT]], double* undef, align 8 405; CHECK-NEXT: [[MAXNUM:%.*]] = call double @llvm.maxnum.f64(double [[X_EXT]], double [[Y_EXT]]) 406; CHECK-NEXT: [[TRUNC:%.*]] = fptrunc double [[MAXNUM]] to float 407; CHECK-NEXT: ret float [[TRUNC]] 408; 409 %x.ext = fpext float %x to double 410 %y.ext = fpext float %y to double 411 store double %y.ext, double* undef 412 %maxnum = call double @llvm.maxnum.f64(double %x.ext, double %y.ext) 413 %trunc = fptrunc double %maxnum to float 414 ret float %trunc 415} 416