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 @noop_maxnum_f32(float %x) { 133; CHECK-LABEL: @noop_maxnum_f32( 134; CHECK-NEXT: ret float [[X:%.*]] 135; 136 %y = call float @llvm.maxnum.f32(float %x, float %x) 137 ret float %y 138} 139 140define float @maxnum_f32_nan_val(float %x) { 141; CHECK-LABEL: @maxnum_f32_nan_val( 142; CHECK-NEXT: ret float [[X:%.*]] 143; 144 %y = call float @llvm.maxnum.f32(float 0x7FF8000000000000, float %x) 145 ret float %y 146} 147 148define float @maxnum_f32_val_nan(float %x) { 149; CHECK-LABEL: @maxnum_f32_val_nan( 150; CHECK-NEXT: ret float [[X:%.*]] 151; 152 %y = call float @llvm.maxnum.f32(float %x, float 0x7FF8000000000000) 153 ret float %y 154} 155 156define float @fold_maxnum_f32_undef_undef(float %x) { 157; CHECK-LABEL: @fold_maxnum_f32_undef_undef( 158; CHECK-NEXT: ret float undef 159; 160 %val = call float @llvm.maxnum.f32(float undef, float undef) 161 ret float %val 162} 163 164define float @fold_maxnum_f32_val_undef(float %x) { 165; CHECK-LABEL: @fold_maxnum_f32_val_undef( 166; CHECK-NEXT: ret float [[X:%.*]] 167; 168 %val = call float @llvm.maxnum.f32(float %x, float undef) 169 ret float %val 170} 171 172define float @fold_maxnum_f32_undef_val(float %x) { 173; CHECK-LABEL: @fold_maxnum_f32_undef_val( 174; CHECK-NEXT: ret float [[X:%.*]] 175; 176 %val = call float @llvm.maxnum.f32(float undef, float %x) 177 ret float %val 178} 179 180define float @maxnum_x_maxnum_x_y(float %x, float %y) { 181; CHECK-LABEL: @maxnum_x_maxnum_x_y( 182; CHECK-NEXT: [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]]) 183; CHECK-NEXT: ret float [[A]] 184; 185 %a = call float @llvm.maxnum.f32(float %x, float %y) 186 %b = call float @llvm.maxnum.f32(float %x, float %a) 187 ret float %b 188} 189 190define float @maxnum_y_maxnum_x_y(float %x, float %y) { 191; CHECK-LABEL: @maxnum_y_maxnum_x_y( 192; CHECK-NEXT: [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]]) 193; CHECK-NEXT: ret float [[A]] 194; 195 %a = call float @llvm.maxnum.f32(float %x, float %y) 196 %b = call float @llvm.maxnum.f32(float %y, float %a) 197 ret float %b 198} 199 200define float @maxnum_z_maxnum_x_y(float %x, float %y, float %z) { 201; CHECK-LABEL: @maxnum_z_maxnum_x_y( 202; CHECK-NEXT: [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]]) 203; CHECK-NEXT: [[B:%.*]] = call float @llvm.maxnum.f32(float [[Z:%.*]], float [[A]]) 204; CHECK-NEXT: ret float [[B]] 205; 206 %a = call float @llvm.maxnum.f32(float %x, float %y) 207 %b = call float @llvm.maxnum.f32(float %z, float %a) 208 ret float %b 209} 210 211define float @maxnum_maxnum_x_y_z(float %x, float %y, float %z) { 212; CHECK-LABEL: @maxnum_maxnum_x_y_z( 213; CHECK-NEXT: [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]]) 214; CHECK-NEXT: [[B:%.*]] = call float @llvm.maxnum.f32(float [[A]], float [[Z:%.*]]) 215; CHECK-NEXT: ret float [[B]] 216; 217 %a = call float @llvm.maxnum.f32(float %x, float %y) 218 %b = call float @llvm.maxnum.f32(float %a, float %z) 219 ret float %b 220} 221 222define float @maxnum4(float %x, float %y, float %z, float %w) { 223; CHECK-LABEL: @maxnum4( 224; CHECK-NEXT: [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]]) 225; CHECK-NEXT: [[B:%.*]] = call float @llvm.maxnum.f32(float [[Z:%.*]], float [[W:%.*]]) 226; CHECK-NEXT: [[C:%.*]] = call float @llvm.maxnum.f32(float [[A]], float [[B]]) 227; CHECK-NEXT: ret float [[C]] 228; 229 %a = call float @llvm.maxnum.f32(float %x, float %y) 230 %b = call float @llvm.maxnum.f32(float %z, float %w) 231 %c = call float @llvm.maxnum.f32(float %a, float %b) 232 ret float %c 233} 234 235define float @fold_maxnum_f32_inf_val(float %x) { 236; CHECK-LABEL: @fold_maxnum_f32_inf_val( 237; CHECK-NEXT: ret float 0x7FF0000000000000 238; 239 %val = call float @llvm.maxnum.f32(float 0x7FF0000000000000, float %x) 240 ret float %val 241} 242 243define float @fold_maxnum_f32_neginf_val(float %x) { 244; CHECK-LABEL: @fold_maxnum_f32_neginf_val( 245; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float 0xFFF0000000000000) 246; CHECK-NEXT: ret float [[VAL]] 247; 248 %val = call float @llvm.maxnum.f32(float 0xFFF0000000000000, float %x) 249 ret float %val 250} 251 252; PR37404 - https://bugs.llvm.org/show_bug.cgi?id=37404 253 254define <2 x float> @neg_neg(<2 x float> %x, <2 x float> %y) { 255; CHECK-LABEL: @neg_neg( 256; CHECK-NEXT: [[TMP1:%.*]] = call <2 x float> @llvm.minnum.v2f32(<2 x float> [[X:%.*]], <2 x float> [[Y:%.*]]) 257; CHECK-NEXT: [[R:%.*]] = fsub <2 x float> <float -0.000000e+00, float -0.000000e+00>, [[TMP1]] 258; CHECK-NEXT: ret <2 x float> [[R]] 259; 260 %negx = fsub <2 x float> <float -0.0, float -0.0>, %x 261 %negy = fsub <2 x float> <float -0.0, float -0.0>, %y 262 %r = call <2 x float> @llvm.maxnum.v2f32(<2 x float> %negx, <2 x float> %negy) 263 ret <2 x float> %r 264} 265 266; FMF is not required, but it should be propagated from the intrinsic (not the fnegs). 267 268define float @neg_neg_vec_fmf(float %x, float %y) { 269; CHECK-LABEL: @neg_neg_vec_fmf( 270; CHECK-NEXT: [[TMP1:%.*]] = call fast float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]]) 271; CHECK-NEXT: [[R:%.*]] = fsub fast float -0.000000e+00, [[TMP1]] 272; CHECK-NEXT: ret float [[R]] 273; 274 %negx = fsub arcp float -0.0, %x 275 %negy = fsub afn float -0.0, %y 276 %r = call fast float @llvm.maxnum.f32(float %negx, float %negy) 277 ret float %r 278} 279 280; 1 extra use of an intermediate value should still allow the fold, 281; but 2 would require more instructions than we started with. 282 283declare void @use(float) 284define float @neg_neg_extra_use_x(float %x, float %y) { 285; CHECK-LABEL: @neg_neg_extra_use_x( 286; CHECK-NEXT: [[NEGX:%.*]] = fsub float -0.000000e+00, [[X:%.*]] 287; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.minnum.f32(float [[X]], float [[Y:%.*]]) 288; CHECK-NEXT: [[R:%.*]] = fsub float -0.000000e+00, [[TMP1]] 289; CHECK-NEXT: call void @use(float [[NEGX]]) 290; CHECK-NEXT: ret float [[R]] 291; 292 %negx = fsub float -0.0, %x 293 %negy = fsub float -0.0, %y 294 %r = call float @llvm.maxnum.f32(float %negx, float %negy) 295 call void @use(float %negx) 296 ret float %r 297} 298 299define float @neg_neg_extra_use_y(float %x, float %y) { 300; CHECK-LABEL: @neg_neg_extra_use_y( 301; CHECK-NEXT: [[NEGY:%.*]] = fsub float -0.000000e+00, [[Y:%.*]] 302; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y]]) 303; CHECK-NEXT: [[R:%.*]] = fsub float -0.000000e+00, [[TMP1]] 304; CHECK-NEXT: call void @use(float [[NEGY]]) 305; CHECK-NEXT: ret float [[R]] 306; 307 %negx = fsub float -0.0, %x 308 %negy = fsub float -0.0, %y 309 %r = call float @llvm.maxnum.f32(float %negx, float %negy) 310 call void @use(float %negy) 311 ret float %r 312} 313 314define float @neg_neg_extra_use_x_and_y(float %x, float %y) { 315; CHECK-LABEL: @neg_neg_extra_use_x_and_y( 316; CHECK-NEXT: [[NEGX:%.*]] = fsub float -0.000000e+00, [[X:%.*]] 317; CHECK-NEXT: [[NEGY:%.*]] = fsub float -0.000000e+00, [[Y:%.*]] 318; CHECK-NEXT: [[R:%.*]] = call float @llvm.maxnum.f32(float [[NEGX]], float [[NEGY]]) 319; CHECK-NEXT: call void @use(float [[NEGX]]) 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 %negx) 327 call void @use(float %negy) 328 ret float %r 329} 330 331