1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -instsimplify -S | FileCheck %s 3 4; fneg (fneg X) ==> X 5define float @fneg_fneg_var(float %a) { 6; CHECK-LABEL: @fneg_fneg_var( 7; CHECK-NEXT: ret float [[A:%.*]] 8; 9 %r = fneg float %a 10 %r1 = fneg float %r 11 ret float %r1 12} 13 14; fneg (fsub -0.0, X) ==> X 15define float @fsub_-0_x(float %a) { 16; CHECK-LABEL: @fsub_-0_x( 17; CHECK-NEXT: ret float [[A:%.*]] 18; 19 %t1 = fsub float -0.0, %a 20 %ret = fneg float %t1 21 ret float %ret 22} 23 24define <2 x float> @fsub_-0_x_vec(<2 x float> %a) { 25; CHECK-LABEL: @fsub_-0_x_vec( 26; CHECK-NEXT: ret <2 x float> [[A:%.*]] 27; 28 %t1 = fsub <2 x float> <float -0.0, float -0.0>, %a 29 %ret = fneg <2 x float> %t1 30 ret <2 x float> %ret 31} 32 33define <2 x float> @fsub_-0_x_vec_undef_elts(<2 x float> %a) { 34; CHECK-LABEL: @fsub_-0_x_vec_undef_elts( 35; CHECK-NEXT: ret <2 x float> [[A:%.*]] 36; 37 %t1 = fsub <2 x float> <float -0.0, float undef>, %a 38 %ret = fneg <2 x float> %t1 39 ret <2 x float> %ret 40} 41 42define <2 x float> @fsub_negzero_vec_undef_elts(<2 x float> %x) { 43; CHECK-LABEL: @fsub_negzero_vec_undef_elts( 44; CHECK-NEXT: ret <2 x float> [[X:%.*]] 45; 46 %r = fsub nsz <2 x float> %x, <float undef, float -0.0> 47 ret <2 x float> %r 48} 49 50; fsub -0.0, (fsub -0.0, X) ==> X 51define float @fsub_-0_-0_x(float %a) { 52; CHECK-LABEL: @fsub_-0_-0_x( 53; CHECK-NEXT: ret float [[A:%.*]] 54; 55 %t1 = fsub float -0.0, %a 56 %ret = fsub float -0.0, %t1 57 ret float %ret 58} 59 60; fsub -0.0, (fneg X) ==> X 61define float @fneg_x(float %a) { 62; CHECK-LABEL: @fneg_x( 63; CHECK-NEXT: ret float [[A:%.*]] 64; 65 %t1 = fneg float %a 66 %ret = fsub float -0.0, %t1 67 ret float %ret 68} 69 70define <2 x float> @fsub_-0_-0_x_vec(<2 x float> %a) { 71; CHECK-LABEL: @fsub_-0_-0_x_vec( 72; CHECK-NEXT: ret <2 x float> [[A:%.*]] 73; 74 %t1 = fsub <2 x float> <float -0.0, float -0.0>, %a 75 %ret = fsub <2 x float> <float -0.0, float -0.0>, %t1 76 ret <2 x float> %ret 77} 78 79define <2 x float> @fneg_x_vec(<2 x float> %a) { 80; CHECK-LABEL: @fneg_x_vec( 81; CHECK-NEXT: ret <2 x float> [[A:%.*]] 82; 83 %t1 = fneg <2 x float> %a 84 %ret = fsub <2 x float> <float -0.0, float -0.0>, %t1 85 ret <2 x float> %ret 86} 87 88define <2 x float> @fsub_-0_-0_x_vec_undef_elts(<2 x float> %a) { 89; CHECK-LABEL: @fsub_-0_-0_x_vec_undef_elts( 90; CHECK-NEXT: ret <2 x float> [[A:%.*]] 91; 92 %t1 = fsub <2 x float> <float undef, float -0.0>, %a 93 %ret = fsub <2 x float> <float -0.0, float undef>, %t1 94 ret <2 x float> %ret 95} 96 97define <2 x float> @fneg_x_vec_undef_elts(<2 x float> %a) { 98; CHECK-LABEL: @fneg_x_vec_undef_elts( 99; CHECK-NEXT: ret <2 x float> [[A:%.*]] 100; 101 %t1 = fneg <2 x float> %a 102 %ret = fsub <2 x float> <float -0.0, float undef>, %t1 103 ret <2 x float> %ret 104} 105 106; fsub -0.0, (fsub 0.0, X) != X 107define float @fsub_-0_0_x(float %a) { 108; CHECK-LABEL: @fsub_-0_0_x( 109; CHECK-NEXT: [[T1:%.*]] = fsub float 0.000000e+00, [[A:%.*]] 110; CHECK-NEXT: [[RET:%.*]] = fsub float -0.000000e+00, [[T1]] 111; CHECK-NEXT: ret float [[RET]] 112; 113 %t1 = fsub float 0.0, %a 114 %ret = fsub float -0.0, %t1 115 ret float %ret 116} 117 118; fsub 0.0, (fsub -0.0, X) != X 119define float @fsub_0_-0_x(float %a) { 120; CHECK-LABEL: @fsub_0_-0_x( 121; CHECK-NEXT: [[T1:%.*]] = fsub float -0.000000e+00, [[A:%.*]] 122; CHECK-NEXT: [[RET:%.*]] = fsub float 0.000000e+00, [[T1]] 123; CHECK-NEXT: ret float [[RET]] 124; 125 %t1 = fsub float -0.0, %a 126 %ret = fsub float 0.0, %t1 127 ret float %ret 128} 129 130; fsub X, 0 ==> X 131define float @fsub_x_0(float %x) { 132; CHECK-LABEL: @fsub_x_0( 133; CHECK-NEXT: ret float [[X:%.*]] 134; 135 %r = fsub float %x, 0.0 136 ret float %r 137} 138 139define <2 x float> @fsub_x_0_vec_undef(<2 x float> %x) { 140; CHECK-LABEL: @fsub_x_0_vec_undef( 141; CHECK-NEXT: ret <2 x float> [[X:%.*]] 142; 143 %r = fsub <2 x float> %x, <float undef, float 0.0> 144 ret <2 x float> %r 145} 146 147; fadd X, -0 ==> X 148define float @fadd_x_n0(float %a) { 149; CHECK-LABEL: @fadd_x_n0( 150; CHECK-NEXT: ret float [[A:%.*]] 151; 152 %ret = fadd float %a, -0.0 153 ret float %ret 154} 155 156define <2 x float> @fadd_x_n0_vec_undef_elt(<2 x float> %a) { 157; CHECK-LABEL: @fadd_x_n0_vec_undef_elt( 158; CHECK-NEXT: ret <2 x float> [[A:%.*]] 159; 160 %ret = fadd <2 x float> %a, <float -0.0, float undef> 161 ret <2 x float> %ret 162} 163 164; fmul X, 1.0 ==> X 165define double @fmul_X_1(double %a) { 166; CHECK-LABEL: @fmul_X_1( 167; CHECK-NEXT: ret double [[A:%.*]] 168; 169 %b = fmul double 1.0, %a 170 ret double %b 171} 172 173; PR2642 174define <4 x float> @fmul_X_1_vec(<4 x float> %x) { 175; CHECK-LABEL: @fmul_X_1_vec( 176; CHECK-NEXT: ret <4 x float> [[X:%.*]] 177; 178 %m = fmul <4 x float> %x, <float 1.0, float 1.0, float 1.0, float 1.0> 179 ret <4 x float> %m 180} 181 182; fdiv X, 1.0 ==> X 183define float @fdiv_x_1(float %a) { 184; CHECK-LABEL: @fdiv_x_1( 185; CHECK-NEXT: ret float [[A:%.*]] 186; 187 %ret = fdiv float %a, 1.0 188 ret float %ret 189} 190 191; We can't optimize away the fadd in this test because the input 192; value to the function and subsequently to the fadd may be -0.0. 193; In that one special case, the result of the fadd should be +0.0 194; rather than the first parameter of the fadd. 195 196; Fragile test warning: We need 6 sqrt calls to trigger the bug 197; because the internal logic has a magic recursion limit of 6. 198; This is presented without any explanation or ability to customize. 199 200declare float @sqrtf(float) 201 202define float @PR22688(float %x) { 203; CHECK-LABEL: @PR22688( 204; CHECK-NEXT: [[TMP1:%.*]] = call float @sqrtf(float [[X:%.*]]) 205; CHECK-NEXT: [[TMP2:%.*]] = call float @sqrtf(float [[TMP1]]) 206; CHECK-NEXT: [[TMP3:%.*]] = call float @sqrtf(float [[TMP2]]) 207; CHECK-NEXT: [[TMP4:%.*]] = call float @sqrtf(float [[TMP3]]) 208; CHECK-NEXT: [[TMP5:%.*]] = call float @sqrtf(float [[TMP4]]) 209; CHECK-NEXT: [[TMP6:%.*]] = call float @sqrtf(float [[TMP5]]) 210; CHECK-NEXT: [[TMP7:%.*]] = fadd float [[TMP6]], 0.000000e+00 211; CHECK-NEXT: ret float [[TMP7]] 212; 213 %1 = call float @sqrtf(float %x) 214 %2 = call float @sqrtf(float %1) 215 %3 = call float @sqrtf(float %2) 216 %4 = call float @sqrtf(float %3) 217 %5 = call float @sqrtf(float %4) 218 %6 = call float @sqrtf(float %5) 219 %7 = fadd float %6, 0.0 220 ret float %7 221} 222 223declare float @llvm.fabs.f32(float) 224declare <2 x float> @llvm.fabs.v2f32(<2 x float>) 225declare float @llvm.sqrt.f32(float) 226 227define float @fabs_select_positive_constants(i32 %c) { 228; CHECK-LABEL: @fabs_select_positive_constants( 229; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 230; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 1.000000e+00, float 2.000000e+00 231; CHECK-NEXT: ret float [[SELECT]] 232; 233 %cmp = icmp eq i32 %c, 0 234 %select = select i1 %cmp, float 1.0, float 2.0 235 %fabs = call float @llvm.fabs.f32(float %select) 236 ret float %fabs 237} 238 239define <2 x float> @fabs_select_positive_constants_vector(i32 %c) { 240; CHECK-LABEL: @fabs_select_positive_constants_vector( 241; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 242; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 1.000000e+00, float 1.000000e+00>, <2 x float> <float 2.000000e+00, float 2.000000e+00> 243; CHECK-NEXT: ret <2 x float> [[SELECT]] 244; 245 %cmp = icmp eq i32 %c, 0 246 %select = select i1 %cmp, <2 x float> <float 1.0, float 1.0>, <2 x float> <float 2.0, float 2.0> 247 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 248 ret <2 x float> %fabs 249} 250 251define float @fabs_select_constant_variable(i32 %c, float %x) { 252; CHECK-LABEL: @fabs_select_constant_variable( 253; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 254; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 1.000000e+00, float [[X:%.*]] 255; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) 256; CHECK-NEXT: ret float [[FABS]] 257; 258 %cmp = icmp eq i32 %c, 0 259 %select = select i1 %cmp, float 1.0, float %x 260 %fabs = call float @llvm.fabs.f32(float %select) 261 ret float %fabs 262} 263 264define <2 x float> @fabs_select_constant_variable_vector(i32 %c, <2 x float> %x) { 265; CHECK-LABEL: @fabs_select_constant_variable_vector( 266; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 267; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 1.000000e+00, float 1.000000e+00>, <2 x float> [[X:%.*]] 268; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]]) 269; CHECK-NEXT: ret <2 x float> [[FABS]] 270; 271 %cmp = icmp eq i32 %c, 0 272 %select = select i1 %cmp, <2 x float> <float 1.0, float 1.0>, <2 x float> %x 273 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 274 ret <2 x float> %fabs 275} 276 277define float @fabs_select_neg0_pos0(i32 %c) { 278; CHECK-LABEL: @fabs_select_neg0_pos0( 279; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 280; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float -0.000000e+00, float 0.000000e+00 281; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) 282; CHECK-NEXT: ret float [[FABS]] 283; 284 %cmp = icmp eq i32 %c, 0 285 %select = select i1 %cmp, float -0.0, float 0.0 286 %fabs = call float @llvm.fabs.f32(float %select) 287 ret float %fabs 288} 289 290define <2 x float> @fabs_select_neg0_pos0_vector(i32 %c) { 291; CHECK-LABEL: @fabs_select_neg0_pos0_vector( 292; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 293; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float -0.000000e+00, float -0.000000e+00>, <2 x float> zeroinitializer 294; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]]) 295; CHECK-NEXT: ret <2 x float> [[FABS]] 296; 297 %cmp = icmp eq i32 %c, 0 298 %select = select i1 %cmp, <2 x float> <float -0.0, float -0.0>, <2 x float> <float 0.0, float 0.0> 299 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 300 ret <2 x float> %fabs 301} 302 303define float @fabs_select_neg0_neg1(i32 %c) { 304; CHECK-LABEL: @fabs_select_neg0_neg1( 305; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 306; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float -0.000000e+00, float -1.000000e+00 307; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) 308; CHECK-NEXT: ret float [[FABS]] 309; 310 %cmp = icmp eq i32 %c, 0 311 %select = select i1 %cmp, float -0.0, float -1.0 312 %fabs = call float @llvm.fabs.f32(float %select) 313 ret float %fabs 314} 315 316define <2 x float> @fabs_select_neg0_neg1_vector(i32 %c) { 317; CHECK-LABEL: @fabs_select_neg0_neg1_vector( 318; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 319; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float -0.000000e+00, float -0.000000e+00>, <2 x float> <float -1.000000e+00, float -1.000000e+00> 320; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]]) 321; CHECK-NEXT: ret <2 x float> [[FABS]] 322; 323 %cmp = icmp eq i32 %c, 0 324 %select = select i1 %cmp, <2 x float> <float -0.0, float -0.0>, <2 x float> <float -1.0, float -1.0> 325 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 326 ret <2 x float> %fabs 327} 328 329define float @fabs_select_nan_nan(i32 %c) { 330; CHECK-LABEL: @fabs_select_nan_nan( 331; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 332; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 0x7FF8000000000000, float 0x7FF8000100000000 333; CHECK-NEXT: ret float [[SELECT]] 334; 335 %cmp = icmp eq i32 %c, 0 336 %select = select i1 %cmp, float 0x7FF8000000000000, float 0x7FF8000100000000 337 %fabs = call float @llvm.fabs.f32(float %select) 338 ret float %fabs 339} 340 341define <2 x float> @fabs_select_nan_nan_vector(i32 %c) { 342; CHECK-LABEL: @fabs_select_nan_nan_vector( 343; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 344; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000> 345; CHECK-NEXT: ret <2 x float> [[SELECT]] 346; 347 %cmp = icmp eq i32 %c, 0 348 %select = select i1 %cmp, <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000> 349 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 350 ret <2 x float> %fabs 351} 352 353define float @fabs_select_negnan_nan(i32 %c) { 354; CHECK-LABEL: @fabs_select_negnan_nan( 355; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 356; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float 0x7FF8000000000000 357; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) 358; CHECK-NEXT: ret float [[FABS]] 359; 360 %cmp = icmp eq i32 %c, 0 361 %select = select i1 %cmp, float 0xFFF8000000000000, float 0x7FF8000000000000 362 %fabs = call float @llvm.fabs.f32(float %select) 363 ret float %fabs 364} 365 366define <2 x float> @fabs_select_negnan_nan_vector(i32 %c) { 367; CHECK-LABEL: @fabs_select_negnan_nan_vector( 368; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 369; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000> 370; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]]) 371; CHECK-NEXT: ret <2 x float> [[FABS]] 372; 373 %cmp = icmp eq i32 %c, 0 374 %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000> 375 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 376 ret <2 x float> %fabs 377} 378 379define float @fabs_select_negnan_negnan(i32 %c) { 380; CHECK-LABEL: @fabs_select_negnan_negnan( 381; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 382; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float 0x7FF8000100000000 383; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) 384; CHECK-NEXT: ret float [[FABS]] 385; 386 %cmp = icmp eq i32 %c, 0 387 %select = select i1 %cmp, float 0xFFF8000000000000, float 0x7FF8000100000000 388 %fabs = call float @llvm.fabs.f32(float %select) 389 ret float %fabs 390} 391 392define <2 x float> @fabs_select_negnan_negnan_vector(i32 %c) { 393; CHECK-LABEL: @fabs_select_negnan_negnan_vector( 394; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 395; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000> 396; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]]) 397; CHECK-NEXT: ret <2 x float> [[FABS]] 398; 399 %cmp = icmp eq i32 %c, 0 400 %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000> 401 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 402 ret <2 x float> %fabs 403} 404 405define float @fabs_select_negnan_negzero(i32 %c) { 406; CHECK-LABEL: @fabs_select_negnan_negzero( 407; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 408; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float -0.000000e+00 409; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) 410; CHECK-NEXT: ret float [[FABS]] 411; 412 %cmp = icmp eq i32 %c, 0 413 %select = select i1 %cmp, float 0xFFF8000000000000, float -0.0 414 %fabs = call float @llvm.fabs.f32(float %select) 415 ret float %fabs 416} 417 418define <2 x float> @fabs_select_negnan_negzero_vector(i32 %c) { 419; CHECK-LABEL: @fabs_select_negnan_negzero_vector( 420; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 421; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float -0.000000e+00, float -0.000000e+00> 422; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]]) 423; CHECK-NEXT: ret <2 x float> [[FABS]] 424; 425 %cmp = icmp eq i32 %c, 0 426 %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float -0.0, float -0.0> 427 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 428 ret <2 x float> %fabs 429} 430 431define float @fabs_select_negnan_zero(i32 %c) { 432; CHECK-LABEL: @fabs_select_negnan_zero( 433; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 434; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float 0.000000e+00 435; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) 436; CHECK-NEXT: ret float [[FABS]] 437; 438 %cmp = icmp eq i32 %c, 0 439 %select = select i1 %cmp, float 0xFFF8000000000000, float 0.0 440 %fabs = call float @llvm.fabs.f32(float %select) 441 ret float %fabs 442} 443 444define <2 x float> @fabs_select_negnan_zero_vector(i32 %c) { 445; CHECK-LABEL: @fabs_select_negnan_zero_vector( 446; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 447; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> zeroinitializer 448; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]]) 449; CHECK-NEXT: ret <2 x float> [[FABS]] 450; 451 %cmp = icmp eq i32 %c, 0 452 %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0.0, float 0.0> 453 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 454 ret <2 x float> %fabs 455} 456 457; The fabs can't be eliminated because llvm.sqrt.f32 may return -0 or NaN with 458; an arbitrary sign bit. 459define float @fabs_sqrt(float %a) { 460; CHECK-LABEL: @fabs_sqrt( 461; CHECK-NEXT: [[SQRT:%.*]] = call float @llvm.sqrt.f32(float [[A:%.*]]) 462; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]]) 463; CHECK-NEXT: ret float [[FABS]] 464; 465 %sqrt = call float @llvm.sqrt.f32(float %a) 466 %fabs = call float @llvm.fabs.f32(float %sqrt) 467 ret float %fabs 468} 469 470; The fabs can't be eliminated because the nnan sqrt may still return -0. 471define float @fabs_sqrt_nnan(float %a) { 472; CHECK-LABEL: @fabs_sqrt_nnan( 473; CHECK-NEXT: [[SQRT:%.*]] = call nnan float @llvm.sqrt.f32(float [[A:%.*]]) 474; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]]) 475; CHECK-NEXT: ret float [[FABS]] 476; 477 %sqrt = call nnan float @llvm.sqrt.f32(float %a) 478 %fabs = call float @llvm.fabs.f32(float %sqrt) 479 ret float %fabs 480} 481 482; The fabs can't be eliminated because the nsz sqrt may still return NaN. 483define float @fabs_sqrt_nsz(float %a) { 484; CHECK-LABEL: @fabs_sqrt_nsz( 485; CHECK-NEXT: [[SQRT:%.*]] = call nsz float @llvm.sqrt.f32(float [[A:%.*]]) 486; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]]) 487; CHECK-NEXT: ret float [[FABS]] 488; 489 %sqrt = call nsz float @llvm.sqrt.f32(float %a) 490 %fabs = call float @llvm.fabs.f32(float %sqrt) 491 ret float %fabs 492} 493 494; The fabs can be eliminated because we're nsz and nnan. 495define float @fabs_sqrt_nnan_nsz(float %a) { 496; CHECK-LABEL: @fabs_sqrt_nnan_nsz( 497; CHECK-NEXT: [[SQRT:%.*]] = call nnan nsz float @llvm.sqrt.f32(float [[A:%.*]]) 498; CHECK-NEXT: ret float [[SQRT]] 499; 500 %sqrt = call nnan nsz float @llvm.sqrt.f32(float %a) 501 %fabs = call float @llvm.fabs.f32(float %sqrt) 502 ret float %fabs 503} 504 505; The second fabs can be eliminated because the operand to sqrt cannot be -0. 506define float @fabs_sqrt_nnan_fabs(float %a) { 507; CHECK-LABEL: @fabs_sqrt_nnan_fabs( 508; CHECK-NEXT: [[B:%.*]] = call float @llvm.fabs.f32(float [[A:%.*]]) 509; CHECK-NEXT: [[SQRT:%.*]] = call nnan float @llvm.sqrt.f32(float [[B]]) 510; CHECK-NEXT: ret float [[SQRT]] 511; 512 %b = call float @llvm.fabs.f32(float %a) 513 %sqrt = call nnan float @llvm.sqrt.f32(float %b) 514 %fabs = call float @llvm.fabs.f32(float %sqrt) 515 ret float %fabs 516} 517 518define float @fabs_select_positive_constants_vector_extract(i32 %c) { 519; CHECK-LABEL: @fabs_select_positive_constants_vector_extract( 520; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 521; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 1.000000e+00, float 1.000000e+00>, <2 x float> <float 2.000000e+00, float 2.000000e+00> 522; CHECK-NEXT: [[EXTRACT:%.*]] = extractelement <2 x float> [[SELECT]], i32 0 523; CHECK-NEXT: ret float [[EXTRACT]] 524; 525 %cmp = icmp eq i32 %c, 0 526 %select = select i1 %cmp, <2 x float> <float 1.0, float 1.0>, <2 x float> <float 2.0, float 2.0> 527 %extract = extractelement <2 x float> %select, i32 0 528 %fabs = call float @llvm.fabs.f32(float %extract) 529 ret float %fabs 530} 531 532declare float @llvm.minnum.f32(float, float) 533declare float @llvm.maxnum.f32(float, float) 534declare double @llvm.minnum.f64(double, double) 535declare double @llvm.maxnum.f64(double, double) 536declare <2 x double> @llvm.minnum.v2f64(<2 x double>, <2 x double>) 537declare <2 x double> @llvm.maxnum.v2f64(<2 x double>, <2 x double>) 538 539; From the LangRef for minnum/maxnum: 540; "If either operand is a NaN, returns the other non-NaN operand." 541 542define double @maxnum_nan_op0(double %x) { 543; CHECK-LABEL: @maxnum_nan_op0( 544; CHECK-NEXT: ret double [[X:%.*]] 545; 546 %r = call double @llvm.maxnum.f64(double 0x7ff8000000000000, double %x) 547 ret double %r 548} 549 550define double @maxnum_nan_op1(double %x) { 551; CHECK-LABEL: @maxnum_nan_op1( 552; CHECK-NEXT: ret double [[X:%.*]] 553; 554 %r = call double @llvm.maxnum.f64(double %x, double 0x7ff800000000dead) 555 ret double %r 556} 557 558define double @minnum_nan_op0(double %x) { 559; CHECK-LABEL: @minnum_nan_op0( 560; CHECK-NEXT: ret double [[X:%.*]] 561; 562 %r = call double @llvm.minnum.f64(double 0x7ff8000dead00000, double %x) 563 ret double %r 564} 565 566define double @minnum_nan_op1(double %x) { 567; CHECK-LABEL: @minnum_nan_op1( 568; CHECK-NEXT: ret double [[X:%.*]] 569; 570 %r = call double @llvm.minnum.f64(double %x, double 0x7ff800dead00dead) 571 ret double %r 572} 573 574define <2 x double> @maxnum_nan_op0_vec(<2 x double> %x) { 575; CHECK-LABEL: @maxnum_nan_op0_vec( 576; CHECK-NEXT: ret <2 x double> [[X:%.*]] 577; 578 %r = call <2 x double> @llvm.maxnum.v2f64(<2 x double> <double 0x7ff8000000000000, double undef>, <2 x double> %x) 579 ret <2 x double> %r 580} 581 582define <2 x double> @maxnum_nan_op1_vec(<2 x double> %x) { 583; CHECK-LABEL: @maxnum_nan_op1_vec( 584; CHECK-NEXT: ret <2 x double> [[X:%.*]] 585; 586 %r = call <2 x double> @llvm.maxnum.v2f64(<2 x double> %x, <2 x double> <double 0x7ff800000000dead, double 0x7ff8ffffffffffff>) 587 ret <2 x double> %r 588} 589 590define <2 x double> @minnum_nan_op0_vec(<2 x double> %x) { 591; CHECK-LABEL: @minnum_nan_op0_vec( 592; CHECK-NEXT: ret <2 x double> [[X:%.*]] 593; 594 %r = call <2 x double> @llvm.minnum.v2f64(<2 x double> <double undef, double 0x7ff8000dead00000>, <2 x double> %x) 595 ret <2 x double> %r 596} 597 598define <2 x double> @minnum_nan_op1_vec(<2 x double> %x) { 599; CHECK-LABEL: @minnum_nan_op1_vec( 600; CHECK-NEXT: ret <2 x double> [[X:%.*]] 601; 602 %r = call <2 x double> @llvm.minnum.v2f64(<2 x double> %x, <2 x double> <double 0x7ff800dead00dead, double 0x7ff800dead00dead>) 603 ret <2 x double> %r 604} 605 606define float @maxnum_undef_op1(float %x) { 607; CHECK-LABEL: @maxnum_undef_op1( 608; CHECK-NEXT: ret float [[X:%.*]] 609; 610 %val = call float @llvm.maxnum.f32(float %x, float undef) 611 ret float %val 612} 613 614define float @maxnum_undef_op0(float %x) { 615; CHECK-LABEL: @maxnum_undef_op0( 616; CHECK-NEXT: ret float [[X:%.*]] 617; 618 %val = call float @llvm.maxnum.f32(float undef, float %x) 619 ret float %val 620} 621 622define float @minnum_undef_op1(float %x) { 623; CHECK-LABEL: @minnum_undef_op1( 624; CHECK-NEXT: ret float [[X:%.*]] 625; 626 %val = call float @llvm.minnum.f32(float %x, float undef) 627 ret float %val 628} 629 630define float @minnum_undef_op0(float %x) { 631; CHECK-LABEL: @minnum_undef_op0( 632; CHECK-NEXT: ret float [[X:%.*]] 633; 634 %val = call float @llvm.minnum.f32(float undef, float %x) 635 ret float %val 636} 637 638define float @minnum_undef_undef(float %x) { 639; CHECK-LABEL: @minnum_undef_undef( 640; CHECK-NEXT: ret float undef 641; 642 %val = call float @llvm.minnum.f32(float undef, float undef) 643 ret float %val 644} 645 646define float @maxnum_undef_undef(float %x) { 647; CHECK-LABEL: @maxnum_undef_undef( 648; CHECK-NEXT: ret float undef 649; 650 %val = call float @llvm.maxnum.f32(float undef, float undef) 651 ret float %val 652} 653 654define float @minnum_same_args(float %x) { 655; CHECK-LABEL: @minnum_same_args( 656; CHECK-NEXT: ret float [[X:%.*]] 657; 658 %y = call float @llvm.minnum.f32(float %x, float %x) 659 ret float %y 660} 661 662define float @maxnum_same_args(float %x) { 663; CHECK-LABEL: @maxnum_same_args( 664; CHECK-NEXT: ret float [[X:%.*]] 665; 666 %y = call float @llvm.maxnum.f32(float %x, float %x) 667 ret float %y 668} 669 670define float @minnum_x_minnum_x_y(float %x, float %y) { 671; CHECK-LABEL: @minnum_x_minnum_x_y( 672; CHECK-NEXT: [[A:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]]) 673; CHECK-NEXT: ret float [[A]] 674; 675 %a = call float @llvm.minnum.f32(float %x, float %y) 676 %b = call float @llvm.minnum.f32(float %x, float %a) 677 ret float %b 678} 679 680define float @minnum_y_minnum_x_y(float %x, float %y) { 681; CHECK-LABEL: @minnum_y_minnum_x_y( 682; CHECK-NEXT: [[A:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]]) 683; CHECK-NEXT: ret float [[A]] 684; 685 %a = call float @llvm.minnum.f32(float %x, float %y) 686 %b = call float @llvm.minnum.f32(float %y, float %a) 687 ret float %b 688} 689 690define float @minnum_x_y_minnum_x(float %x, float %y) { 691; CHECK-LABEL: @minnum_x_y_minnum_x( 692; CHECK-NEXT: [[A:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]]) 693; CHECK-NEXT: ret float [[A]] 694; 695 %a = call float @llvm.minnum.f32(float %x, float %y) 696 %b = call float @llvm.minnum.f32(float %a, float %x) 697 ret float %b 698} 699 700define float @minnum_x_y_minnum_y(float %x, float %y) { 701; CHECK-LABEL: @minnum_x_y_minnum_y( 702; CHECK-NEXT: [[A:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]]) 703; CHECK-NEXT: ret float [[A]] 704; 705 %a = call float @llvm.minnum.f32(float %x, float %y) 706 %b = call float @llvm.minnum.f32(float %a, float %y) 707 ret float %b 708} 709 710; negative test 711 712define float @minnum_z_minnum_x_y(float %x, float %y, float %z) { 713; CHECK-LABEL: @minnum_z_minnum_x_y( 714; CHECK-NEXT: [[A:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]]) 715; CHECK-NEXT: [[B:%.*]] = call float @llvm.minnum.f32(float [[Z:%.*]], float [[A]]) 716; CHECK-NEXT: ret float [[B]] 717; 718 %a = call float @llvm.minnum.f32(float %x, float %y) 719 %b = call float @llvm.minnum.f32(float %z, float %a) 720 ret float %b 721} 722 723; negative test 724 725define float @minnum_x_y_minnum_z(float %x, float %y, float %z) { 726; CHECK-LABEL: @minnum_x_y_minnum_z( 727; CHECK-NEXT: [[A:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]]) 728; CHECK-NEXT: [[B:%.*]] = call float @llvm.minnum.f32(float [[A]], float [[Z:%.*]]) 729; CHECK-NEXT: ret float [[B]] 730; 731 %a = call float @llvm.minnum.f32(float %x, float %y) 732 %b = call float @llvm.minnum.f32(float %a, float %z) 733 ret float %b 734} 735 736; minnum(X, -INF) --> -INF 737 738define float @minnum_neginf(float %x) { 739; CHECK-LABEL: @minnum_neginf( 740; CHECK-NEXT: ret float 0xFFF0000000000000 741; 742 %val = call float @llvm.minnum.f32(float %x, float 0xFFF0000000000000) 743 ret float %val 744} 745 746define <2 x double> @minnum_neginf_commute_vec(<2 x double> %x) { 747; CHECK-LABEL: @minnum_neginf_commute_vec( 748; CHECK-NEXT: ret <2 x double> <double 0xFFF0000000000000, double 0xFFF0000000000000> 749; 750 %r = call <2 x double> @llvm.minnum.v2f64(<2 x double> <double 0xFFF0000000000000, double 0xFFF0000000000000>, <2 x double> %x) 751 ret <2 x double> %r 752} 753 754; negative test 755 756define float @minnum_inf(float %x) { 757; CHECK-LABEL: @minnum_inf( 758; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.minnum.f32(float 0x7FF0000000000000, float [[X:%.*]]) 759; CHECK-NEXT: ret float [[VAL]] 760; 761 %val = call float @llvm.minnum.f32(float 0x7FF0000000000000, float %x) 762 ret float %val 763} 764define float @maxnum_x_maxnum_x_y(float %x, float %y) { 765; CHECK-LABEL: @maxnum_x_maxnum_x_y( 766; CHECK-NEXT: [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]]) 767; CHECK-NEXT: ret float [[A]] 768; 769 %a = call float @llvm.maxnum.f32(float %x, float %y) 770 %b = call float @llvm.maxnum.f32(float %x, float %a) 771 ret float %b 772} 773 774define float @maxnum_y_maxnum_x_y(float %x, float %y) { 775; CHECK-LABEL: @maxnum_y_maxnum_x_y( 776; CHECK-NEXT: [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]]) 777; CHECK-NEXT: ret float [[A]] 778; 779 %a = call float @llvm.maxnum.f32(float %x, float %y) 780 %b = call float @llvm.maxnum.f32(float %y, float %a) 781 ret float %b 782} 783 784define float @maxnum_x_y_maxnum_x(float %x, float %y) { 785; CHECK-LABEL: @maxnum_x_y_maxnum_x( 786; CHECK-NEXT: [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]]) 787; CHECK-NEXT: ret float [[A]] 788; 789 %a = call float @llvm.maxnum.f32(float %x, float %y) 790 %b = call float @llvm.maxnum.f32(float %a, float %x) 791 ret float %b 792} 793 794define float @maxnum_x_y_maxnum_y(float %x, float %y) { 795; CHECK-LABEL: @maxnum_x_y_maxnum_y( 796; CHECK-NEXT: [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]]) 797; CHECK-NEXT: ret float [[A]] 798; 799 %a = call float @llvm.maxnum.f32(float %x, float %y) 800 %b = call float @llvm.maxnum.f32(float %a, float %y) 801 ret float %b 802} 803 804; negative test 805 806define float @maxnum_z_maxnum_x_y(float %x, float %y, float %z) { 807; CHECK-LABEL: @maxnum_z_maxnum_x_y( 808; CHECK-NEXT: [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]]) 809; CHECK-NEXT: [[B:%.*]] = call float @llvm.maxnum.f32(float [[Z:%.*]], float [[A]]) 810; CHECK-NEXT: ret float [[B]] 811; 812 %a = call float @llvm.maxnum.f32(float %x, float %y) 813 %b = call float @llvm.maxnum.f32(float %z, float %a) 814 ret float %b 815} 816 817; negative test 818 819define float @maxnum_x_y_maxnum_z(float %x, float %y, float %z) { 820; CHECK-LABEL: @maxnum_x_y_maxnum_z( 821; CHECK-NEXT: [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]]) 822; CHECK-NEXT: [[B:%.*]] = call float @llvm.maxnum.f32(float [[A]], float [[Z:%.*]]) 823; CHECK-NEXT: ret float [[B]] 824; 825 %a = call float @llvm.maxnum.f32(float %x, float %y) 826 %b = call float @llvm.maxnum.f32(float %a, float %z) 827 ret float %b 828} 829 830; maxnum(X, INF) --> INF 831 832define <2 x double> @maxnum_inf(<2 x double> %x) { 833; CHECK-LABEL: @maxnum_inf( 834; CHECK-NEXT: ret <2 x double> <double 0x7FF0000000000000, double 0x7FF0000000000000> 835; 836 %val = call <2 x double> @llvm.maxnum.v2f64(<2 x double> %x, <2 x double><double 0x7FF0000000000000, double 0x7FF0000000000000>) 837 ret <2 x double> %val 838} 839 840define float @maxnum_inf_commute(float %x) { 841; CHECK-LABEL: @maxnum_inf_commute( 842; CHECK-NEXT: ret float 0x7FF0000000000000 843; 844 %val = call float @llvm.maxnum.f32(float 0x7FF0000000000000, float %x) 845 ret float %val 846} 847 848; negative test 849 850define float @maxnum_neginf(float %x) { 851; CHECK-LABEL: @maxnum_neginf( 852; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.maxnum.f32(float 0xFFF0000000000000, float [[X:%.*]]) 853; CHECK-NEXT: ret float [[VAL]] 854; 855 %val = call float @llvm.maxnum.f32(float 0xFFF0000000000000, float %x) 856 ret float %val 857} 858 859declare float @llvm.minimum.f32(float, float) 860declare float @llvm.maximum.f32(float, float) 861declare double @llvm.minimum.f64(double, double) 862declare double @llvm.maximum.f64(double, double) 863declare <2 x double> @llvm.minimum.v2f64(<2 x double>, <2 x double>) 864declare <2 x double> @llvm.maximum.v2f64(<2 x double>, <2 x double>) 865 866; From the LangRef for minimum/maximum: 867; "If either operand is a NaN, returns NaN." 868 869define double @maximum_nan_op0(double %x) { 870; CHECK-LABEL: @maximum_nan_op0( 871; CHECK-NEXT: ret double 0x7FF8000000000000 872; 873 %r = call double @llvm.maximum.f64(double 0x7ff8000000000000, double %x) 874 ret double %r 875} 876 877define double @maximum_nan_op1(double %x) { 878; CHECK-LABEL: @maximum_nan_op1( 879; CHECK-NEXT: ret double 0x7FF800000000DEAD 880; 881 %r = call double @llvm.maximum.f64(double %x, double 0x7ff800000000dead) 882 ret double %r 883} 884 885define double @minimum_nan_op0(double %x) { 886; CHECK-LABEL: @minimum_nan_op0( 887; CHECK-NEXT: ret double 0x7FF8000DEAD00000 888; 889 %r = call double @llvm.minimum.f64(double 0x7ff8000dead00000, double %x) 890 ret double %r 891} 892 893define double @minimum_nan_op1(double %x) { 894; CHECK-LABEL: @minimum_nan_op1( 895; CHECK-NEXT: ret double 0x7FF800DEAD00DEAD 896; 897 %r = call double @llvm.minimum.f64(double %x, double 0x7ff800dead00dead) 898 ret double %r 899} 900 901define <2 x double> @maximum_nan_op0_vec(<2 x double> %x) { 902; CHECK-LABEL: @maximum_nan_op0_vec( 903; CHECK-NEXT: ret <2 x double> <double 0x7FF8000000000000, double undef> 904; 905 %r = call <2 x double> @llvm.maximum.v2f64(<2 x double> <double 0x7ff8000000000000, double undef>, <2 x double> %x) 906 ret <2 x double> %r 907} 908 909define <2 x double> @maximum_nan_op1_vec(<2 x double> %x) { 910; CHECK-LABEL: @maximum_nan_op1_vec( 911; CHECK-NEXT: ret <2 x double> <double 0x7FF800000000DEAD, double 0x7FF8FFFFFFFFFFFF> 912; 913 %r = call <2 x double> @llvm.maximum.v2f64(<2 x double> %x, <2 x double> <double 0x7ff800000000dead, double 0x7ff8ffffffffffff>) 914 ret <2 x double> %r 915} 916 917define <2 x double> @minimum_nan_op0_vec(<2 x double> %x) { 918; CHECK-LABEL: @minimum_nan_op0_vec( 919; CHECK-NEXT: ret <2 x double> <double undef, double 0x7FF8000DEAD00000> 920; 921 %r = call <2 x double> @llvm.minimum.v2f64(<2 x double> <double undef, double 0x7ff8000dead00000>, <2 x double> %x) 922 ret <2 x double> %r 923} 924 925define <2 x double> @minimum_nan_op1_vec(<2 x double> %x) { 926; CHECK-LABEL: @minimum_nan_op1_vec( 927; CHECK-NEXT: ret <2 x double> <double 0x7FF800DEAD00DEAD, double 0x7FF800DEAD00DEAD> 928; 929 %r = call <2 x double> @llvm.minimum.v2f64(<2 x double> %x, <2 x double> <double 0x7ff800dead00dead, double 0x7ff800dead00dead>) 930 ret <2 x double> %r 931} 932 933define float @maximum_undef_op1(float %x) { 934; CHECK-LABEL: @maximum_undef_op1( 935; CHECK-NEXT: ret float [[X:%.*]] 936; 937 %val = call float @llvm.maximum.f32(float %x, float undef) 938 ret float %val 939} 940 941define float @maximum_undef_op0(float %x) { 942; CHECK-LABEL: @maximum_undef_op0( 943; CHECK-NEXT: ret float [[X:%.*]] 944; 945 %val = call float @llvm.maximum.f32(float undef, float %x) 946 ret float %val 947} 948 949define float @minimum_undef_op1(float %x) { 950; CHECK-LABEL: @minimum_undef_op1( 951; CHECK-NEXT: ret float [[X:%.*]] 952; 953 %val = call float @llvm.minimum.f32(float %x, float undef) 954 ret float %val 955} 956 957define float @minimum_undef_op0(float %x) { 958; CHECK-LABEL: @minimum_undef_op0( 959; CHECK-NEXT: ret float [[X:%.*]] 960; 961 %val = call float @llvm.minimum.f32(float undef, float %x) 962 ret float %val 963} 964 965define float @minimum_undef_undef(float %x) { 966; CHECK-LABEL: @minimum_undef_undef( 967; CHECK-NEXT: ret float undef 968; 969 %val = call float @llvm.minimum.f32(float undef, float undef) 970 ret float %val 971} 972 973define float @maximum_undef_undef(float %x) { 974; CHECK-LABEL: @maximum_undef_undef( 975; CHECK-NEXT: ret float undef 976; 977 %val = call float @llvm.maximum.f32(float undef, float undef) 978 ret float %val 979} 980 981define float @minimum_same_args(float %x) { 982; CHECK-LABEL: @minimum_same_args( 983; CHECK-NEXT: ret float [[X:%.*]] 984; 985 %y = call float @llvm.minimum.f32(float %x, float %x) 986 ret float %y 987} 988 989define float @maximum_same_args(float %x) { 990; CHECK-LABEL: @maximum_same_args( 991; CHECK-NEXT: ret float [[X:%.*]] 992; 993 %y = call float @llvm.maximum.f32(float %x, float %x) 994 ret float %y 995} 996 997define float @minimum_x_minimum_x_y(float %x, float %y) { 998; CHECK-LABEL: @minimum_x_minimum_x_y( 999; CHECK-NEXT: [[A:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]]) 1000; CHECK-NEXT: ret float [[A]] 1001; 1002 %a = call float @llvm.minimum.f32(float %x, float %y) 1003 %b = call float @llvm.minimum.f32(float %x, float %a) 1004 ret float %b 1005} 1006 1007define float @minimum_y_minimum_x_y(float %x, float %y) { 1008; CHECK-LABEL: @minimum_y_minimum_x_y( 1009; CHECK-NEXT: [[A:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]]) 1010; CHECK-NEXT: ret float [[A]] 1011; 1012 %a = call float @llvm.minimum.f32(float %x, float %y) 1013 %b = call float @llvm.minimum.f32(float %y, float %a) 1014 ret float %b 1015} 1016 1017define float @minimum_x_y_minimum_x(float %x, float %y) { 1018; CHECK-LABEL: @minimum_x_y_minimum_x( 1019; CHECK-NEXT: [[A:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]]) 1020; CHECK-NEXT: ret float [[A]] 1021; 1022 %a = call float @llvm.minimum.f32(float %x, float %y) 1023 %b = call float @llvm.minimum.f32(float %a, float %x) 1024 ret float %b 1025} 1026 1027define float @minimum_x_y_minimum_y(float %x, float %y) { 1028; CHECK-LABEL: @minimum_x_y_minimum_y( 1029; CHECK-NEXT: [[A:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]]) 1030; CHECK-NEXT: ret float [[A]] 1031; 1032 %a = call float @llvm.minimum.f32(float %x, float %y) 1033 %b = call float @llvm.minimum.f32(float %a, float %y) 1034 ret float %b 1035} 1036 1037; negative test 1038 1039define float @minimum_z_minimum_x_y(float %x, float %y, float %z) { 1040; CHECK-LABEL: @minimum_z_minimum_x_y( 1041; CHECK-NEXT: [[A:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]]) 1042; CHECK-NEXT: [[B:%.*]] = call float @llvm.minimum.f32(float [[Z:%.*]], float [[A]]) 1043; CHECK-NEXT: ret float [[B]] 1044; 1045 %a = call float @llvm.minimum.f32(float %x, float %y) 1046 %b = call float @llvm.minimum.f32(float %z, float %a) 1047 ret float %b 1048} 1049 1050; negative test 1051 1052define float @minimum_x_y_minimum_z(float %x, float %y, float %z) { 1053; CHECK-LABEL: @minimum_x_y_minimum_z( 1054; CHECK-NEXT: [[A:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]]) 1055; CHECK-NEXT: [[B:%.*]] = call float @llvm.minimum.f32(float [[A]], float [[Z:%.*]]) 1056; CHECK-NEXT: ret float [[B]] 1057; 1058 %a = call float @llvm.minimum.f32(float %x, float %y) 1059 %b = call float @llvm.minimum.f32(float %a, float %z) 1060 ret float %b 1061} 1062 1063; minimum(X, -INF) --> -INF 1064 1065define float @minimum_neginf(float %x) { 1066; CHECK-LABEL: @minimum_neginf( 1067; CHECK-NEXT: ret float 0xFFF0000000000000 1068; 1069 %val = call float @llvm.minimum.f32(float %x, float 0xFFF0000000000000) 1070 ret float %val 1071} 1072 1073define <2 x double> @minimum_neginf_commute_vec(<2 x double> %x) { 1074; CHECK-LABEL: @minimum_neginf_commute_vec( 1075; CHECK-NEXT: ret <2 x double> <double 0xFFF0000000000000, double 0xFFF0000000000000> 1076; 1077 %r = call <2 x double> @llvm.minimum.v2f64(<2 x double> <double 0xFFF0000000000000, double 0xFFF0000000000000>, <2 x double> %x) 1078 ret <2 x double> %r 1079} 1080 1081; negative test 1082 1083define float @minimum_inf(float %x) { 1084; CHECK-LABEL: @minimum_inf( 1085; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.minimum.f32(float 0x7FF0000000000000, float [[X:%.*]]) 1086; CHECK-NEXT: ret float [[VAL]] 1087; 1088 %val = call float @llvm.minimum.f32(float 0x7FF0000000000000, float %x) 1089 ret float %val 1090} 1091define float @maximum_x_maximum_x_y(float %x, float %y) { 1092; CHECK-LABEL: @maximum_x_maximum_x_y( 1093; CHECK-NEXT: [[A:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]]) 1094; CHECK-NEXT: ret float [[A]] 1095; 1096 %a = call float @llvm.maximum.f32(float %x, float %y) 1097 %b = call float @llvm.maximum.f32(float %x, float %a) 1098 ret float %b 1099} 1100 1101define float @maximum_y_maximum_x_y(float %x, float %y) { 1102; CHECK-LABEL: @maximum_y_maximum_x_y( 1103; CHECK-NEXT: [[A:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]]) 1104; CHECK-NEXT: ret float [[A]] 1105; 1106 %a = call float @llvm.maximum.f32(float %x, float %y) 1107 %b = call float @llvm.maximum.f32(float %y, float %a) 1108 ret float %b 1109} 1110 1111define float @maximum_x_y_maximum_x(float %x, float %y) { 1112; CHECK-LABEL: @maximum_x_y_maximum_x( 1113; CHECK-NEXT: [[A:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]]) 1114; CHECK-NEXT: ret float [[A]] 1115; 1116 %a = call float @llvm.maximum.f32(float %x, float %y) 1117 %b = call float @llvm.maximum.f32(float %a, float %x) 1118 ret float %b 1119} 1120 1121define float @maximum_x_y_maximum_y(float %x, float %y) { 1122; CHECK-LABEL: @maximum_x_y_maximum_y( 1123; CHECK-NEXT: [[A:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]]) 1124; CHECK-NEXT: ret float [[A]] 1125; 1126 %a = call float @llvm.maximum.f32(float %x, float %y) 1127 %b = call float @llvm.maximum.f32(float %a, float %y) 1128 ret float %b 1129} 1130 1131; negative test 1132 1133define float @maximum_z_maximum_x_y(float %x, float %y, float %z) { 1134; CHECK-LABEL: @maximum_z_maximum_x_y( 1135; CHECK-NEXT: [[A:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]]) 1136; CHECK-NEXT: [[B:%.*]] = call float @llvm.maximum.f32(float [[Z:%.*]], float [[A]]) 1137; CHECK-NEXT: ret float [[B]] 1138; 1139 %a = call float @llvm.maximum.f32(float %x, float %y) 1140 %b = call float @llvm.maximum.f32(float %z, float %a) 1141 ret float %b 1142} 1143 1144; negative test 1145 1146define float @maximum_x_y_maximum_z(float %x, float %y, float %z) { 1147; CHECK-LABEL: @maximum_x_y_maximum_z( 1148; CHECK-NEXT: [[A:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]]) 1149; CHECK-NEXT: [[B:%.*]] = call float @llvm.maximum.f32(float [[A]], float [[Z:%.*]]) 1150; CHECK-NEXT: ret float [[B]] 1151; 1152 %a = call float @llvm.maximum.f32(float %x, float %y) 1153 %b = call float @llvm.maximum.f32(float %a, float %z) 1154 ret float %b 1155} 1156 1157; maximum(X, INF) --> INF 1158 1159define <2 x double> @maximum_inf(<2 x double> %x) { 1160; CHECK-LABEL: @maximum_inf( 1161; CHECK-NEXT: ret <2 x double> <double 0x7FF0000000000000, double 0x7FF0000000000000> 1162; 1163 %val = call <2 x double> @llvm.maximum.v2f64(<2 x double> %x, <2 x double><double 0x7FF0000000000000, double 0x7FF0000000000000>) 1164 ret <2 x double> %val 1165} 1166 1167define float @maximum_inf_commute(float %x) { 1168; CHECK-LABEL: @maximum_inf_commute( 1169; CHECK-NEXT: ret float 0x7FF0000000000000 1170; 1171 %val = call float @llvm.maximum.f32(float 0x7FF0000000000000, float %x) 1172 ret float %val 1173} 1174 1175; Y - (Y - X) --> X 1176 1177define float @fsub_fsub_common_op(float %x, float %y) { 1178; CHECK-LABEL: @fsub_fsub_common_op( 1179; CHECK-NEXT: ret float [[X:%.*]] 1180; 1181 %s = fsub float %y, %x 1182 %r = fsub reassoc nsz float %y, %s 1183 ret float %r 1184} 1185 1186define <2 x float> @fsub_fsub_common_op_vec(<2 x float> %x, <2 x float> %y) { 1187; CHECK-LABEL: @fsub_fsub_common_op_vec( 1188; CHECK-NEXT: ret <2 x float> [[X:%.*]] 1189; 1190 %s = fsub <2 x float> %y, %x 1191 %r = fsub reassoc nsz <2 x float> %y, %s 1192 ret <2 x float> %r 1193} 1194 1195; Negative test - fsub is not commutative. 1196; Y - (X - Y) --> (Y - X) + Y (canonicalized) 1197 1198define float @fsub_fsub_wrong_common_op(float %x, float %y) { 1199; CHECK-LABEL: @fsub_fsub_wrong_common_op( 1200; CHECK-NEXT: [[S:%.*]] = fsub float [[X:%.*]], [[Y:%.*]] 1201; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz float [[Y]], [[S]] 1202; CHECK-NEXT: ret float [[R]] 1203; 1204 %s = fsub float %x, %y 1205 %r = fsub reassoc nsz float %y, %s 1206 ret float %r 1207} 1208 1209; Negative test - negated operand needed. 1210; (Y - X) - Y --> -X 1211 1212define float @fsub_fsub_common_op_wrong_commute(float %x, float %y) { 1213; CHECK-LABEL: @fsub_fsub_common_op_wrong_commute( 1214; CHECK-NEXT: [[S:%.*]] = fsub float [[Y:%.*]], [[X:%.*]] 1215; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz float [[S]], [[Y]] 1216; CHECK-NEXT: ret float [[R]] 1217; 1218 %s = fsub float %y, %x 1219 %r = fsub reassoc nsz float %s, %y 1220 ret float %r 1221} 1222 1223; Negative test - fsub is not commutative. 1224; (X - Y) - Y --> ? 1225 1226define float @fsub_fsub_wrong_common_op_wrong_commute(float %x, float %y) { 1227; CHECK-LABEL: @fsub_fsub_wrong_common_op_wrong_commute( 1228; CHECK-NEXT: [[S:%.*]] = fsub float [[X:%.*]], [[Y:%.*]] 1229; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz float [[S]], [[Y]] 1230; CHECK-NEXT: ret float [[R]] 1231; 1232 %s = fsub float %x, %y 1233 %r = fsub reassoc nsz float %s, %y 1234 ret float %r 1235} 1236 1237; (Y + X) - Y --> X 1238 1239define float @fadd_fsub_common_op(float %x, float %y) { 1240; CHECK-LABEL: @fadd_fsub_common_op( 1241; CHECK-NEXT: ret float [[X:%.*]] 1242; 1243 %a = fadd float %y, %x 1244 %r = fsub reassoc nsz float %a, %y 1245 ret float %r 1246} 1247 1248; (X + Y) - Y --> X 1249 1250define <2 x float> @fadd_fsub_common_op_commute_vec(<2 x float> %x, <2 x float> %y) { 1251; CHECK-LABEL: @fadd_fsub_common_op_commute_vec( 1252; CHECK-NEXT: ret <2 x float> [[X:%.*]] 1253; 1254 %a = fadd <2 x float> %x, %y 1255 %r = fsub reassoc nsz <2 x float> %a, %y 1256 ret <2 x float> %r 1257} 1258 1259; Negative test - negated operand needed. 1260; Y - (Y + X) --> -X 1261 1262define float @fadd_fsub_common_op_wrong_commute(float %x, float %y) { 1263; CHECK-LABEL: @fadd_fsub_common_op_wrong_commute( 1264; CHECK-NEXT: [[A:%.*]] = fadd float [[Y:%.*]], [[X:%.*]] 1265; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz float [[Y]], [[A]] 1266; CHECK-NEXT: ret float [[R]] 1267; 1268 %a = fadd float %y, %x 1269 %r = fsub reassoc nsz float %y, %a 1270 ret float %r 1271} 1272 1273; Negative test - negated operand needed. 1274; Y - (X + Y) --> -X 1275 1276define float @fadd_fsub_common_op_wrong_commute_commute(float %x, float %y) { 1277; CHECK-LABEL: @fadd_fsub_common_op_wrong_commute_commute( 1278; CHECK-NEXT: [[A:%.*]] = fadd float [[X:%.*]], [[Y:%.*]] 1279; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz float [[Y]], [[A]] 1280; CHECK-NEXT: ret float [[R]] 1281; 1282 %a = fadd float %x, %y 1283 %r = fsub reassoc nsz float %y, %a 1284 ret float %r 1285} 1286 1287; Y + (X - Y) --> X 1288 1289define <2 x float> @fsub_fadd_common_op_vec(<2 x float> %x, <2 x float> %y) { 1290; CHECK-LABEL: @fsub_fadd_common_op_vec( 1291; CHECK-NEXT: ret <2 x float> [[X:%.*]] 1292; 1293 %s = fsub <2 x float> %x, %y 1294 %r = fadd reassoc nsz <2 x float> %y, %s 1295 ret <2 x float> %r 1296} 1297 1298; (X - Y) + Y --> X 1299 1300define float @fsub_fadd_common_op_commute(float %x, float %y) { 1301; CHECK-LABEL: @fsub_fadd_common_op_commute( 1302; CHECK-NEXT: ret float [[X:%.*]] 1303; 1304 %s = fsub float %x, %y 1305 %r = fadd reassoc nsz float %s, %y 1306 ret float %r 1307} 1308 1309; Negative test. 1310; Y + (Y - X) --> ? 1311 1312define float @fsub_fadd_common_op_wrong_commute(float %x, float %y) { 1313; CHECK-LABEL: @fsub_fadd_common_op_wrong_commute( 1314; CHECK-NEXT: [[S:%.*]] = fsub float [[Y:%.*]], [[X:%.*]] 1315; CHECK-NEXT: [[R:%.*]] = fadd reassoc nsz float [[Y]], [[S]] 1316; CHECK-NEXT: ret float [[R]] 1317; 1318 %s = fsub float %y, %x 1319 %r = fadd reassoc nsz float %y, %s 1320 ret float %r 1321} 1322 1323; Negative test. 1324; (Y - X) + Y --> ? 1325 1326define float @fsub_fadd_common_op_wrong_commute_commute(float %x, float %y) { 1327; CHECK-LABEL: @fsub_fadd_common_op_wrong_commute_commute( 1328; CHECK-NEXT: [[S:%.*]] = fsub float [[Y:%.*]], [[X:%.*]] 1329; CHECK-NEXT: [[R:%.*]] = fadd reassoc nsz float [[S]], [[Y]] 1330; CHECK-NEXT: ret float [[R]] 1331; 1332 %s = fsub float %y, %x 1333 %r = fadd reassoc nsz float %s, %y 1334 ret float %r 1335} 1336 1337; PR46627 - https://bugs.llvm.org/show_bug.cgi?id=46627 1338 1339define float @maxnum_with_poszero_op(float %a) { 1340; CHECK-LABEL: @maxnum_with_poszero_op( 1341; CHECK-NEXT: [[MAX:%.*]] = call float @llvm.maxnum.f32(float [[A:%.*]], float 0.000000e+00) 1342; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]]) 1343; CHECK-NEXT: ret float [[FABS]] 1344; 1345 %max = call float @llvm.maxnum.f32(float %a, float 0.0) 1346 %fabs = call float @llvm.fabs.f32(float %max) 1347 ret float %fabs 1348} 1349 1350define float @maxnum_with_poszero_op_commute(float %a) { 1351; CHECK-LABEL: @maxnum_with_poszero_op_commute( 1352; CHECK-NEXT: [[SQRT:%.*]] = call float @llvm.sqrt.f32(float [[A:%.*]]) 1353; CHECK-NEXT: [[MAX:%.*]] = call float @llvm.maxnum.f32(float 0.000000e+00, float [[SQRT]]) 1354; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]]) 1355; CHECK-NEXT: ret float [[FABS]] 1356; 1357 %sqrt = call float @llvm.sqrt.f32(float %a) 1358 %max = call float @llvm.maxnum.f32(float 0.0, float %sqrt) 1359 %fabs = call float @llvm.fabs.f32(float %max) 1360 ret float %fabs 1361} 1362 1363define float @maxnum_with_negzero_op(float %a) { 1364; CHECK-LABEL: @maxnum_with_negzero_op( 1365; CHECK-NEXT: [[NNAN:%.*]] = call nnan float @llvm.sqrt.f32(float [[A:%.*]]) 1366; CHECK-NEXT: [[FABSA:%.*]] = call float @llvm.fabs.f32(float [[NNAN]]) 1367; CHECK-NEXT: [[MAX:%.*]] = call float @llvm.maxnum.f32(float -0.000000e+00, float [[FABSA]]) 1368; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]]) 1369; CHECK-NEXT: ret float [[FABS]] 1370; 1371 %nnan = call nnan float @llvm.sqrt.f32(float %a) 1372 %fabsa = call float @llvm.fabs.f32(float %nnan) 1373 %max = call float @llvm.maxnum.f32(float -0.0, float %fabsa) 1374 %fabs = call float @llvm.fabs.f32(float %max) 1375 ret float %fabs 1376} 1377 1378define float @maxnum_with_negzero_op_commute(float %a) { 1379; CHECK-LABEL: @maxnum_with_negzero_op_commute( 1380; CHECK-NEXT: [[NNAN:%.*]] = call nnan float @llvm.sqrt.f32(float [[A:%.*]]) 1381; CHECK-NEXT: [[FABSA:%.*]] = call float @llvm.fabs.f32(float [[NNAN]]) 1382; CHECK-NEXT: [[MAX:%.*]] = call float @llvm.maxnum.f32(float [[FABSA]], float -0.000000e+00) 1383; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]]) 1384; CHECK-NEXT: ret float [[FABS]] 1385; 1386 %nnan = call nnan float @llvm.sqrt.f32(float %a) 1387 %fabsa = call float @llvm.fabs.f32(float %nnan) 1388 %max = call float @llvm.maxnum.f32(float %fabsa, float -0.0) 1389 %fabs = call float @llvm.fabs.f32(float %max) 1390 ret float %fabs 1391} 1392 1393; If an operand is strictly greater than 0.0, we know the sign of the result of maxnum. 1394 1395define float @maxnum_with_pos_one_op(float %a) { 1396; CHECK-LABEL: @maxnum_with_pos_one_op( 1397; CHECK-NEXT: [[MAX:%.*]] = call float @llvm.maxnum.f32(float [[A:%.*]], float 1.000000e+00) 1398; CHECK-NEXT: ret float [[MAX]] 1399; 1400 %max = call float @llvm.maxnum.f32(float %a, float 1.0) 1401 %fabs = call float @llvm.fabs.f32(float %max) 1402 ret float %fabs 1403} 1404