1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -instcombine < %s | FileCheck %s 3 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+00 14; 15 %x = call float @llvm.maximum.f32(float 1.0, float 2.0) 16 ret float %x 17} 18 19define float @constant_fold_maximum_f32_inv() { 20; CHECK-LABEL: @constant_fold_maximum_f32_inv( 21; CHECK-NEXT: ret float 2.000000e+00 22; 23 %x = call float @llvm.maximum.f32(float 2.0, float 1.0) 24 ret float %x 25} 26 27define float @constant_fold_maximum_f32_nan0() { 28; CHECK-LABEL: @constant_fold_maximum_f32_nan0( 29; CHECK-NEXT: ret float 0x7FF8000000000000 30; 31 %x = call float @llvm.maximum.f32(float 0x7FF8000000000000, float 2.0) 32 ret float %x 33} 34 35define float @constant_fold_maximum_f32_nan1() { 36; CHECK-LABEL: @constant_fold_maximum_f32_nan1( 37; CHECK-NEXT: ret float 0x7FF8000000000000 38; 39 %x = call float @llvm.maximum.f32(float 2.0, float 0x7FF8000000000000) 40 ret float %x 41} 42 43define float @constant_fold_maximum_f32_nan_nan() { 44; CHECK-LABEL: @constant_fold_maximum_f32_nan_nan( 45; CHECK-NEXT: ret float 0x7FF8000000000000 46; 47 %x = call float @llvm.maximum.f32(float 0x7FF8000000000000, float 0x7FF8000000000000) 48 ret float %x 49} 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+00 54; 55 %x = call float @llvm.maximum.f32(float 0.0, float 0.0) 56 ret float %x 57} 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+00 62; 63 %x = call float @llvm.maximum.f32(float 0.0, float -0.0) 64 ret float %x 65} 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+00 70; 71 %x = call float @llvm.maximum.f32(float -0.0, float 0.0) 72 ret float %x 73} 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+00 78; 79 %x = call float @llvm.maximum.f32(float -0.0, float -0.0) 80 ret float %x 81} 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> %x 89} 90 91define double @constant_fold_maximum_f64() { 92; CHECK-LABEL: @constant_fold_maximum_f64( 93; CHECK-NEXT: ret double 2.000000e+00 94; 95 %x = call double @llvm.maximum.f64(double 1.0, double 2.0) 96 ret double %x 97} 98 99define double @constant_fold_maximum_f64_nan0() { 100; CHECK-LABEL: @constant_fold_maximum_f64_nan0( 101; CHECK-NEXT: ret double 0x7FF8000000000000 102; 103 %x = call double @llvm.maximum.f64(double 0x7FF8000000000000, double 2.0) 104 ret double %x 105} 106 107define double @constant_fold_maximum_f64_nan1() { 108; CHECK-LABEL: @constant_fold_maximum_f64_nan1( 109; CHECK-NEXT: ret double 0x7FF8000000000000 110; 111 %x = call double @llvm.maximum.f64(double 2.0, double 0x7FF8000000000000) 112 ret double %x 113} 114 115define double @constant_fold_maximum_f64_nan_nan() { 116; CHECK-LABEL: @constant_fold_maximum_f64_nan_nan( 117; CHECK-NEXT: ret double 0x7FF8000000000000 118; 119 %x = call double @llvm.maximum.f64(double 0x7FF8000000000000, double 0x7FF8000000000000) 120 ret double %x 121} 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 %y 130} 131 132define float @maximum_f32_nan_val(float %x) { 133; CHECK-LABEL: @maximum_f32_nan_val( 134; CHECK-NEXT: ret float 0x7FF8000000000000 135; 136 %y = call float @llvm.maximum.f32(float 0x7FF8000000000000, float %x) 137 ret float %y 138} 139 140define float @maximum_f32_val_nan(float %x) { 141; CHECK-LABEL: @maximum_f32_val_nan( 142; CHECK-NEXT: ret float 0x7FF8000000000000 143; 144 %y = call float @llvm.maximum.f32(float %x, float 0x7FF8000000000000) 145 ret float %y 146} 147 148define float @maximum_f32_1_maximum_val_p0(float %x) { 149; CHECK-LABEL: @maximum_f32_1_maximum_val_p0( 150; CHECK-NEXT: [[RES:%.*]] = call float @llvm.maximum.f32(float %x, float 1.000000e+00) 151; CHECK-NEXT: ret float [[RES]] 152 %y = call float @llvm.maximum.f32(float %x, float 0.0) 153 %z = call float @llvm.maximum.f32(float %y, float 1.0) 154 ret float %z 155} 156 157define float @maximum_f32_1_maximum_p0_val_fast(float %x) { 158; CHECK-LABEL: @maximum_f32_1_maximum_p0_val_fast( 159; CHECK-NEXT: [[RES:%.*]] = call fast float @llvm.maximum.f32(float %x, float 1.000000e+00) 160; CHECK-NEXT: ret float [[RES]] 161 %y = call float @llvm.maximum.f32(float 0.0, float %x) 162 %z = call fast float @llvm.maximum.f32(float %y, float 1.0) 163 ret float %z 164} 165 166define float @maximum_f32_1_maximum_p0_val_nnan_ninf(float %x) { 167; CHECK-LABEL: @maximum_f32_1_maximum_p0_val_nnan_ninf( 168; CHECK-NEXT: [[RES:%.*]] = call nnan ninf float @llvm.maximum.f32(float %x, float 1.000000e+00) 169; CHECK-NEXT: ret float [[RES]] 170 %y = call float @llvm.maximum.f32(float 0.0, float %x) 171 %z = call nnan ninf float @llvm.maximum.f32(float %y, float 1.0) 172 ret float %z 173} 174 175define float @maximum_f32_p0_maximum_val_n0(float %x) { 176; CHECK-LABEL: @maximum_f32_p0_maximum_val_n0( 177; CHECK-NEXT: [[RES:%.*]] = call float @llvm.maximum.f32(float %x, float 0.000000e+00) 178; CHECK-NEXT: ret float [[RES]] 179 %y = call float @llvm.maximum.f32(float %x, float -0.0) 180 %z = call float @llvm.maximum.f32(float %y, float 0.0) 181 ret float %z 182} 183 184define float @maximum_f32_1_maximum_p0_val(float %x) { 185; CHECK-LABEL: @maximum_f32_1_maximum_p0_val( 186; CHECK-NEXT: [[RES:%.*]] = call float @llvm.maximum.f32(float %x, float 1.000000e+00) 187; CHECK-NEXT: ret float [[RES]] 188 %y = call float @llvm.maximum.f32(float 0.0, float %x) 189 %z = call float @llvm.maximum.f32(float %y, float 1.0) 190 ret float %z 191} 192 193define <2 x float> @maximum_f32_1_maximum_val_p0_val_v2f32(<2 x float> %x) { 194; CHECK-LABEL: @maximum_f32_1_maximum_val_p0_val_v2f32( 195; CHECK-NEXT: [[RES:%.*]] = call <2 x float> @llvm.maximum.v2f32(<2 x float> %x, <2 x float> <float 1.000000e+00, float 1.000000e+00>) 196; CHECK-NEXT: ret <2 x float> [[RES]] 197 %y = call <2 x float> @llvm.maximum.v2f32(<2 x float> %x, <2 x float> zeroinitializer) 198 %z = call <2 x float> @llvm.maximum.v2f32(<2 x float> %y, <2 x float><float 1.0, float 1.0>) 199 ret <2 x float> %z 200} 201 202define float @maximum4(float %x, float %y, float %z, float %w) { 203; CHECK-LABEL: @maximum4( 204; CHECK-NEXT: [[A:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]]) 205; CHECK-NEXT: [[B:%.*]] = call float @llvm.maximum.f32(float [[Z:%.*]], float [[W:%.*]]) 206; CHECK-NEXT: [[C:%.*]] = call float @llvm.maximum.f32(float [[A]], float [[B]]) 207; CHECK-NEXT: ret float [[C]] 208; 209 %a = call float @llvm.maximum.f32(float %x, float %y) 210 %b = call float @llvm.maximum.f32(float %z, float %w) 211 %c = call float @llvm.maximum.f32(float %a, float %b) 212 ret float %c 213} 214 215; PR37404 - https://bugs.llvm.org/show_bug.cgi?id=37404 216 217define <2 x float> @neg_neg(<2 x float> %x, <2 x float> %y) { 218; CHECK-LABEL: @neg_neg( 219; CHECK-NEXT: [[TMP1:%.*]] = call <2 x float> @llvm.minimum.v2f32(<2 x float> [[X:%.*]], <2 x float> [[Y:%.*]]) 220; CHECK-NEXT: [[R:%.*]] = fneg <2 x float> [[TMP1]] 221; CHECK-NEXT: ret <2 x float> [[R]] 222; 223 %negx = fsub <2 x float> <float -0.0, float -0.0>, %x 224 %negy = fsub <2 x float> <float -0.0, float -0.0>, %y 225 %r = call <2 x float> @llvm.maximum.v2f32(<2 x float> %negx, <2 x float> %negy) 226 ret <2 x float> %r 227} 228 229define <2 x float> @unary_neg_neg(<2 x float> %x, <2 x float> %y) { 230; CHECK-LABEL: @unary_neg_neg( 231; CHECK-NEXT: [[TMP1:%.*]] = call <2 x float> @llvm.minimum.v2f32(<2 x float> [[X:%.*]], <2 x float> [[Y:%.*]]) 232; CHECK-NEXT: [[R:%.*]] = fneg <2 x float> [[TMP1]] 233; CHECK-NEXT: ret <2 x float> [[R]] 234; 235 %negx = fneg <2 x float> %x 236 %negy = fneg <2 x float> %y 237 %r = call <2 x float> @llvm.maximum.v2f32(<2 x float> %negx, <2 x float> %negy) 238 ret <2 x float> %r 239} 240 241; FMF is not required, but it should be propagated from the intrinsic (not the fnegs). 242 243define float @neg_neg_vec_fmf(float %x, float %y) { 244; CHECK-LABEL: @neg_neg_vec_fmf( 245; CHECK-NEXT: [[TMP1:%.*]] = call fast float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]]) 246; CHECK-NEXT: [[R:%.*]] = fneg fast float [[TMP1]] 247; CHECK-NEXT: ret float [[R]] 248; 249 %negx = fsub arcp float -0.0, %x 250 %negy = fsub afn float -0.0, %y 251 %r = call fast float @llvm.maximum.f32(float %negx, float %negy) 252 ret float %r 253} 254 255define float @unary_neg_neg_vec_fmf(float %x, float %y) { 256; CHECK-LABEL: @unary_neg_neg_vec_fmf( 257; CHECK-NEXT: [[TMP1:%.*]] = call fast float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]]) 258; CHECK-NEXT: [[R:%.*]] = fneg fast float [[TMP1]] 259; CHECK-NEXT: ret float [[R]] 260; 261 %negx = fneg arcp float %x 262 %negy = fneg afn float %y 263 %r = call fast float @llvm.maximum.f32(float %negx, float %negy) 264 ret float %r 265} 266 267; 1 extra use of an intermediate value should still allow the fold, 268; but 2 would require more instructions than we started with. 269 270declare void @use(float) 271define float @neg_neg_extra_use_x(float %x, float %y) { 272; CHECK-LABEL: @neg_neg_extra_use_x( 273; CHECK-NEXT: [[NEGX:%.*]] = fneg float [[X:%.*]] 274; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.minimum.f32(float [[X]], float [[Y:%.*]]) 275; CHECK-NEXT: [[R:%.*]] = fneg float [[TMP1]] 276; CHECK-NEXT: call void @use(float [[NEGX]]) 277; CHECK-NEXT: ret float [[R]] 278; 279 %negx = fsub float -0.0, %x 280 %negy = fsub float -0.0, %y 281 %r = call float @llvm.maximum.f32(float %negx, float %negy) 282 call void @use(float %negx) 283 ret float %r 284} 285 286define float @unary_neg_neg_extra_use_x(float %x, float %y) { 287; CHECK-LABEL: @unary_neg_neg_extra_use_x( 288; CHECK-NEXT: [[NEGX:%.*]] = fneg float [[X:%.*]] 289; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.minimum.f32(float [[X]], float [[Y:%.*]]) 290; CHECK-NEXT: [[R:%.*]] = fneg float [[TMP1]] 291; CHECK-NEXT: call void @use(float [[NEGX]]) 292; CHECK-NEXT: ret float [[R]] 293; 294 %negx = fneg float %x 295 %negy = fneg float %y 296 %r = call float @llvm.maximum.f32(float %negx, float %negy) 297 call void @use(float %negx) 298 ret float %r 299} 300 301define float @neg_neg_extra_use_y(float %x, float %y) { 302; CHECK-LABEL: @neg_neg_extra_use_y( 303; CHECK-NEXT: [[NEGY:%.*]] = fneg float [[Y:%.*]] 304; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y]]) 305; CHECK-NEXT: [[R:%.*]] = fneg float [[TMP1]] 306; CHECK-NEXT: call void @use(float [[NEGY]]) 307; CHECK-NEXT: ret float [[R]] 308; 309 %negx = fsub float -0.0, %x 310 %negy = fsub float -0.0, %y 311 %r = call float @llvm.maximum.f32(float %negx, float %negy) 312 call void @use(float %negy) 313 ret float %r 314} 315 316define float @unary_neg_neg_extra_use_y(float %x, float %y) { 317; CHECK-LABEL: @unary_neg_neg_extra_use_y( 318; CHECK-NEXT: [[NEGY:%.*]] = fneg float [[Y:%.*]] 319; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y]]) 320; CHECK-NEXT: [[R:%.*]] = fneg float [[TMP1]] 321; CHECK-NEXT: call void @use(float [[NEGY]]) 322; CHECK-NEXT: ret float [[R]] 323; 324 %negx = fneg float %x 325 %negy = fneg float %y 326 %r = call float @llvm.maximum.f32(float %negx, float %negy) 327 call void @use(float %negy) 328 ret float %r 329} 330 331define float @neg_neg_extra_use_x_and_y(float %x, float %y) { 332; CHECK-LABEL: @neg_neg_extra_use_x_and_y( 333; CHECK-NEXT: [[NEGX:%.*]] = fneg float [[X:%.*]] 334; CHECK-NEXT: [[NEGY:%.*]] = fneg float [[Y:%.*]] 335; CHECK-NEXT: [[R:%.*]] = call float @llvm.maximum.f32(float [[NEGX]], float [[NEGY]]) 336; CHECK-NEXT: call void @use(float [[NEGX]]) 337; CHECK-NEXT: call void @use(float [[NEGY]]) 338; CHECK-NEXT: ret float [[R]] 339; 340 %negx = fsub float -0.0, %x 341 %negy = fsub float -0.0, %y 342 %r = call float @llvm.maximum.f32(float %negx, float %negy) 343 call void @use(float %negx) 344 call void @use(float %negy) 345 ret float %r 346} 347 348define float @unary_neg_neg_extra_use_x_and_y(float %x, float %y) { 349; CHECK-LABEL: @unary_neg_neg_extra_use_x_and_y( 350; CHECK-NEXT: [[NEGX:%.*]] = fneg float [[X:%.*]] 351; CHECK-NEXT: [[NEGY:%.*]] = fneg float [[Y:%.*]] 352; CHECK-NEXT: [[R:%.*]] = call float @llvm.maximum.f32(float [[NEGX]], float [[NEGY]]) 353; CHECK-NEXT: call void @use(float [[NEGX]]) 354; CHECK-NEXT: call void @use(float [[NEGY]]) 355; CHECK-NEXT: ret float [[R]] 356; 357 %negx = fneg float %x 358 %negy = fneg float %y 359 %r = call float @llvm.maximum.f32(float %negx, float %negy) 360 call void @use(float %negx) 361 call void @use(float %negy) 362 ret float %r 363} 364 365define float @reduce_precision(float %x, float %y) { 366; CHECK-LABEL: @reduce_precision( 367; CHECK-NEXT: [[MAXIMUM:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]]) 368; CHECK-NEXT: ret float [[MAXIMUM]] 369; 370 %x.ext = fpext float %x to double 371 %y.ext = fpext float %y to double 372 %maximum = call double @llvm.maximum.f64(double %x.ext, double %y.ext) 373 %trunc = fptrunc double %maximum to float 374 ret float %trunc 375} 376 377define float @reduce_precision_fmf(float %x, float %y) { 378; CHECK-LABEL: @reduce_precision_fmf( 379; CHECK-NEXT: [[MAXIMUM:%.*]] = call nnan float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]]) 380; CHECK-NEXT: ret float [[MAXIMUM]] 381; 382 %x.ext = fpext float %x to double 383 %y.ext = fpext float %y to double 384 %maximum = call nnan double @llvm.maximum.f64(double %x.ext, double %y.ext) 385 %trunc = fptrunc double %maximum to float 386 ret float %trunc 387} 388