1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=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_poison_elts(<2 x float> %a) { 34; CHECK-LABEL: @fsub_-0_x_vec_poison_elts( 35; CHECK-NEXT: ret <2 x float> [[A:%.*]] 36; 37 %t1 = fsub <2 x float> <float -0.0, float poison>, %a 38 %ret = fneg <2 x float> %t1 39 ret <2 x float> %ret 40} 41 42define <2 x float> @fsub_negzero_vec_poison_elts(<2 x float> %x) { 43; CHECK-LABEL: @fsub_negzero_vec_poison_elts( 44; CHECK-NEXT: ret <2 x float> [[X:%.*]] 45; 46 %r = fsub nsz <2 x float> %x, <float poison, 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_poison_elts(<2 x float> %a) { 89; CHECK-LABEL: @fsub_-0_-0_x_vec_poison_elts( 90; CHECK-NEXT: ret <2 x float> [[A:%.*]] 91; 92 %t1 = fsub <2 x float> <float poison, float -0.0>, %a 93 %ret = fsub <2 x float> <float -0.0, float poison>, %t1 94 ret <2 x float> %ret 95} 96 97define <2 x float> @fneg_x_vec_poison_elts(<2 x float> %a) { 98; CHECK-LABEL: @fneg_x_vec_poison_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 poison>, %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_poison(<2 x float> %x) { 140; CHECK-LABEL: @fsub_x_0_vec_poison( 141; CHECK-NEXT: ret <2 x float> [[X:%.*]] 142; 143 %r = fsub <2 x float> %x, <float poison, 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_poison_elt(<2 x float> %a) { 157; CHECK-LABEL: @fadd_x_n0_vec_poison_elt( 158; CHECK-NEXT: ret <2 x float> [[A:%.*]] 159; 160 %ret = fadd <2 x float> %a, <float -0.0, float poison> 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 173define half @fmul_nnan_ninf_nneg_0.0(i15 %x) { 174; CHECK-LABEL: @fmul_nnan_ninf_nneg_0.0( 175; CHECK-NEXT: ret half 0xH0000 176; 177 %f = uitofp i15 %x to half 178 %r = fmul half %f, 0.0 179 ret half %r 180} 181 182define half @fmul_nnan_ninf_nneg_n0.0(i15 %x) { 183; CHECK-LABEL: @fmul_nnan_ninf_nneg_n0.0( 184; CHECK-NEXT: ret half 0xH8000 185; 186 %f = uitofp i15 %x to half 187 %r = fmul half %f, -0.0 188 ret half %r 189} 190 191; negative test - the int could be big enough to round to INF 192 193define half @fmul_nnan_nneg_0.0(i16 %x) { 194; CHECK-LABEL: @fmul_nnan_nneg_0.0( 195; CHECK-NEXT: [[F:%.*]] = uitofp i16 [[X:%.*]] to half 196; CHECK-NEXT: [[R:%.*]] = fmul half [[F]], 0xH0000 197; CHECK-NEXT: ret half [[R]] 198; 199 %f = uitofp i16 %x to half 200 %r = fmul half %f, 0.0 201 ret half %r 202} 203 204define double @fmul_nnan_ninf_nneg_n0.0_commute(i127 %x) { 205; CHECK-LABEL: @fmul_nnan_ninf_nneg_n0.0_commute( 206; CHECK-NEXT: ret double -0.000000e+00 207; 208 %f = uitofp i127 %x to float 209 %e = fpext float %f to double 210 %r = fmul double -0.0, %e 211 ret double %r 212} 213 214define float @src_mul_nzero_neg(float nofpclass(inf nan pzero psub pnorm) %f) { 215; CHECK-LABEL: @src_mul_nzero_neg( 216; CHECK-NEXT: ret float 0.000000e+00 217; 218 %r = fmul float %f, -0.0 219 ret float %r 220} 221 222define <2 x float> @src_mul_zero_neg(<2 x float> nofpclass(inf nan pzero psub pnorm) %f) { 223; CHECK-LABEL: @src_mul_zero_neg( 224; CHECK-NEXT: ret <2 x float> splat (float -0.000000e+00) 225; 226 %r = fmul <2 x float> <float 0.0, float 0.0>, %f 227 ret <2 x float> %r 228} 229 230define <2 x float> @src_mul_zero_and_nzero_neg(<2 x float> nofpclass(inf nan pzero psub pnorm) %f) { 231; CHECK-LABEL: @src_mul_zero_and_nzero_neg( 232; CHECK-NEXT: ret <2 x float> <float 0.000000e+00, float -0.000000e+00> 233; 234 %r = fmul <2 x float> <float -0.0, float 0.0>, %f 235 ret <2 x float> %r 236} 237 238 239define float @src_muladd_zero_neg(float nofpclass(inf nan pzero psub pnorm) %f, float %add) { 240; CHECK-LABEL: @src_muladd_zero_neg( 241; CHECK-NEXT: [[R:%.*]] = call float @llvm.fmuladd.f32(float [[F:%.*]], float 0.000000e+00, float [[ADD:%.*]]) 242; CHECK-NEXT: ret float [[R]] 243; 244 %r = call float @llvm.fmuladd.f32(float %f, float 0.0, float %add) 245 ret float %r 246} 247 248define float @src_fma_nzero_neg(float nofpclass(inf nan pzero psub pnorm) %f, float %add) { 249; CHECK-LABEL: @src_fma_nzero_neg( 250; CHECK-NEXT: [[R:%.*]] = call float @llvm.fma.f32(float -0.000000e+00, float [[F:%.*]], float [[ADD:%.*]]) 251; CHECK-NEXT: ret float [[R]] 252; 253 %r = call float @llvm.fma.f32(float -0.0, float %f, float %add) 254 ret float %r 255} 256 257 258; Make sure we can infer %x can't be 0 based on assumes. 259define { float, float } @test_fmul_0_assumed_finite(float %x) { 260; CHECK-LABEL: @test_fmul_0_assumed_finite( 261; CHECK-NEXT: [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]]) 262; CHECK-NEXT: [[IS_FINITE_X:%.*]] = fcmp one float [[FABS_X]], 0x7FF0000000000000 263; CHECK-NEXT: call void @llvm.assume(i1 [[IS_FINITE_X]]) 264; CHECK-NEXT: ret { float, float } { float 0.000000e+00, float -0.000000e+00 } 265; 266 %fabs.x = call float @llvm.fabs.f32(float %x) 267 %is.finite.x = fcmp one float %fabs.x, 0x7FF0000000000000 268 call void @llvm.assume(i1 %is.finite.x) 269 %mul.0 = fmul float %fabs.x, 0.0 270 %mul.neg0 = fmul float %fabs.x, -0.0 271 %ins.0 = insertvalue { float, float } poison, float %mul.0, 0 272 %ins.1 = insertvalue { float, float } %ins.0, float %mul.neg0, 1 273 ret { float, float } %ins.1 274} 275 276; negative test - the int could be big enough to round to INF 277 278define double @fmul_nnan_ninf_nneg_0.0_commute(i128 %x) { 279; CHECK-LABEL: @fmul_nnan_ninf_nneg_0.0_commute( 280; CHECK-NEXT: [[F:%.*]] = uitofp i128 [[X:%.*]] to float 281; CHECK-NEXT: [[E:%.*]] = fpext float [[F]] to double 282; CHECK-NEXT: [[R:%.*]] = fmul double 0.000000e+00, [[E]] 283; CHECK-NEXT: ret double [[R]] 284; 285 %f = uitofp i128 %x to float 286 %e = fpext float %f to double 287 %r = fmul double 0.0, %e 288 ret double %r 289} 290 291; PR2642 292define <4 x float> @fmul_X_1_vec(<4 x float> %x) { 293; CHECK-LABEL: @fmul_X_1_vec( 294; CHECK-NEXT: ret <4 x float> [[X:%.*]] 295; 296 %m = fmul <4 x float> %x, <float 1.0, float 1.0, float 1.0, float 1.0> 297 ret <4 x float> %m 298} 299 300; fdiv X, 1.0 ==> X 301define float @fdiv_x_1(float %a) { 302; CHECK-LABEL: @fdiv_x_1( 303; CHECK-NEXT: ret float [[A:%.*]] 304; 305 %ret = fdiv float %a, 1.0 306 ret float %ret 307} 308 309; We can't optimize away the fadd in this test because the input 310; value to the function and subsequently to the fadd may be -0.0. 311; In that one special case, the result of the fadd should be +0.0 312; rather than the first parameter of the fadd. 313 314; Fragile test warning: We need 6 sqrt calls to trigger the bug 315; because the internal logic has a magic recursion limit of 6. 316; This is presented without any explanation or ability to customize. 317 318declare float @sqrtf(float) 319 320define float @PR22688(float %x) { 321; CHECK-LABEL: @PR22688( 322; CHECK-NEXT: [[TMP1:%.*]] = call float @sqrtf(float [[X:%.*]]) 323; CHECK-NEXT: [[TMP2:%.*]] = call float @sqrtf(float [[TMP1]]) 324; CHECK-NEXT: [[TMP3:%.*]] = call float @sqrtf(float [[TMP2]]) 325; CHECK-NEXT: [[TMP4:%.*]] = call float @sqrtf(float [[TMP3]]) 326; CHECK-NEXT: [[TMP5:%.*]] = call float @sqrtf(float [[TMP4]]) 327; CHECK-NEXT: [[TMP6:%.*]] = call float @sqrtf(float [[TMP5]]) 328; CHECK-NEXT: [[TMP7:%.*]] = fadd float [[TMP6]], 0.000000e+00 329; CHECK-NEXT: ret float [[TMP7]] 330; 331 %1 = call float @sqrtf(float %x) 332 %2 = call float @sqrtf(float %1) 333 %3 = call float @sqrtf(float %2) 334 %4 = call float @sqrtf(float %3) 335 %5 = call float @sqrtf(float %4) 336 %6 = call float @sqrtf(float %5) 337 %7 = fadd float %6, 0.0 338 ret float %7 339} 340 341declare float @llvm.fabs.f32(float) 342declare double @llvm.fabs.f64(double) 343declare float @llvm.canonicalize.f32(float) 344declare float @llvm.floor.f32(float) 345declare float @llvm.ceil.f32(float) 346declare float @llvm.trunc.f32(float) 347declare float @llvm.rint.f32(float) 348declare float @llvm.nearbyint.f32(float) 349declare float @llvm.round.f32(float) 350declare float @llvm.roundeven.f32(float) 351declare float @llvm.fptrunc.round.f32.f64(double, metadata) 352declare float @llvm.arithmetic.fence.f32(float) 353declare float @llvm.copysign.f32(float, float) 354declare <2 x float> @llvm.fabs.v2f32(<2 x float>) 355declare float @llvm.sqrt.f32(float) 356declare float @llvm.maxnum.f32(float, float) 357declare void @llvm.assume(i1 noundef) 358 359 360define float @fabs_select_positive_constants(i32 %c) { 361; CHECK-LABEL: @fabs_select_positive_constants( 362; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 363; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 1.000000e+00, float 2.000000e+00 364; CHECK-NEXT: ret float [[SELECT]] 365; 366 %cmp = icmp eq i32 %c, 0 367 %select = select i1 %cmp, float 1.0, float 2.0 368 %fabs = call float @llvm.fabs.f32(float %select) 369 ret float %fabs 370} 371 372define <2 x float> @fabs_select_positive_constants_vector(i32 %c) { 373; CHECK-LABEL: @fabs_select_positive_constants_vector( 374; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 375; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> splat (float 1.000000e+00), <2 x float> splat (float 2.000000e+00) 376; CHECK-NEXT: ret <2 x float> [[SELECT]] 377; 378 %cmp = icmp eq i32 %c, 0 379 %select = select i1 %cmp, <2 x float> <float 1.0, float 1.0>, <2 x float> <float 2.0, float 2.0> 380 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 381 ret <2 x float> %fabs 382} 383 384define float @fabs_select_constant_variable(i32 %c, float %x) { 385; CHECK-LABEL: @fabs_select_constant_variable( 386; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 387; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 1.000000e+00, float [[X:%.*]] 388; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) 389; CHECK-NEXT: ret float [[FABS]] 390; 391 %cmp = icmp eq i32 %c, 0 392 %select = select i1 %cmp, float 1.0, float %x 393 %fabs = call float @llvm.fabs.f32(float %select) 394 ret float %fabs 395} 396 397define <2 x float> @fabs_select_constant_variable_vector(i32 %c, <2 x float> %x) { 398; CHECK-LABEL: @fabs_select_constant_variable_vector( 399; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 400; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> splat (float 1.000000e+00), <2 x float> [[X:%.*]] 401; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]]) 402; CHECK-NEXT: ret <2 x float> [[FABS]] 403; 404 %cmp = icmp eq i32 %c, 0 405 %select = select i1 %cmp, <2 x float> <float 1.0, float 1.0>, <2 x float> %x 406 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 407 ret <2 x float> %fabs 408} 409 410define float @fabs_select_neg0_pos0(i32 %c) { 411; CHECK-LABEL: @fabs_select_neg0_pos0( 412; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 413; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float -0.000000e+00, float 0.000000e+00 414; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) 415; CHECK-NEXT: ret float [[FABS]] 416; 417 %cmp = icmp eq i32 %c, 0 418 %select = select i1 %cmp, float -0.0, float 0.0 419 %fabs = call float @llvm.fabs.f32(float %select) 420 ret float %fabs 421} 422 423define <2 x float> @fabs_select_neg0_pos0_vector(i32 %c) { 424; CHECK-LABEL: @fabs_select_neg0_pos0_vector( 425; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 426; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> splat (float -0.000000e+00), <2 x float> zeroinitializer 427; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]]) 428; CHECK-NEXT: ret <2 x float> [[FABS]] 429; 430 %cmp = icmp eq i32 %c, 0 431 %select = select i1 %cmp, <2 x float> <float -0.0, float -0.0>, <2 x float> <float 0.0, float 0.0> 432 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 433 ret <2 x float> %fabs 434} 435 436define float @fabs_select_neg0_neg1(i32 %c) { 437; CHECK-LABEL: @fabs_select_neg0_neg1( 438; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 439; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float -0.000000e+00, float -1.000000e+00 440; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) 441; CHECK-NEXT: ret float [[FABS]] 442; 443 %cmp = icmp eq i32 %c, 0 444 %select = select i1 %cmp, float -0.0, float -1.0 445 %fabs = call float @llvm.fabs.f32(float %select) 446 ret float %fabs 447} 448 449define <2 x float> @fabs_select_neg0_neg1_vector(i32 %c) { 450; CHECK-LABEL: @fabs_select_neg0_neg1_vector( 451; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 452; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> splat (float -0.000000e+00), <2 x float> splat (float -1.000000e+00) 453; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]]) 454; CHECK-NEXT: ret <2 x float> [[FABS]] 455; 456 %cmp = icmp eq i32 %c, 0 457 %select = select i1 %cmp, <2 x float> <float -0.0, float -0.0>, <2 x float> <float -1.0, float -1.0> 458 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 459 ret <2 x float> %fabs 460} 461 462define float @fabs_select_nan_nan(i32 %c) { 463; CHECK-LABEL: @fabs_select_nan_nan( 464; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 465; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 0x7FF8000000000000, float 0x7FF8000100000000 466; CHECK-NEXT: ret float [[SELECT]] 467; 468 %cmp = icmp eq i32 %c, 0 469 %select = select i1 %cmp, float 0x7FF8000000000000, float 0x7FF8000100000000 470 %fabs = call float @llvm.fabs.f32(float %select) 471 ret float %fabs 472} 473 474define <2 x float> @fabs_select_nan_nan_vector(i32 %c) { 475; CHECK-LABEL: @fabs_select_nan_nan_vector( 476; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 477; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> splat (float 0x7FF8000000000000), <2 x float> splat (float 0x7FF8000100000000) 478; CHECK-NEXT: ret <2 x float> [[SELECT]] 479; 480 %cmp = icmp eq i32 %c, 0 481 %select = select i1 %cmp, <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000> 482 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 483 ret <2 x float> %fabs 484} 485 486define float @fabs_select_negnan_nan(i32 %c) { 487; CHECK-LABEL: @fabs_select_negnan_nan( 488; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 489; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float 0x7FF8000000000000 490; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) 491; CHECK-NEXT: ret float [[FABS]] 492; 493 %cmp = icmp eq i32 %c, 0 494 %select = select i1 %cmp, float 0xFFF8000000000000, float 0x7FF8000000000000 495 %fabs = call float @llvm.fabs.f32(float %select) 496 ret float %fabs 497} 498 499define <2 x float> @fabs_select_negnan_nan_vector(i32 %c) { 500; CHECK-LABEL: @fabs_select_negnan_nan_vector( 501; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 502; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> splat (float 0xFFF8000000000000), <2 x float> splat (float 0x7FF8000000000000) 503; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]]) 504; CHECK-NEXT: ret <2 x float> [[FABS]] 505; 506 %cmp = icmp eq i32 %c, 0 507 %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000> 508 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 509 ret <2 x float> %fabs 510} 511 512define float @fabs_select_negnan_negnan(i32 %c) { 513; CHECK-LABEL: @fabs_select_negnan_negnan( 514; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 515; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float 0x7FF8000100000000 516; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) 517; CHECK-NEXT: ret float [[FABS]] 518; 519 %cmp = icmp eq i32 %c, 0 520 %select = select i1 %cmp, float 0xFFF8000000000000, float 0x7FF8000100000000 521 %fabs = call float @llvm.fabs.f32(float %select) 522 ret float %fabs 523} 524 525define <2 x float> @fabs_select_negnan_negnan_vector(i32 %c) { 526; CHECK-LABEL: @fabs_select_negnan_negnan_vector( 527; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 528; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> splat (float 0xFFF8000000000000), <2 x float> splat (float 0x7FF8000100000000) 529; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]]) 530; CHECK-NEXT: ret <2 x float> [[FABS]] 531; 532 %cmp = icmp eq i32 %c, 0 533 %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000> 534 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 535 ret <2 x float> %fabs 536} 537 538define float @fabs_select_negnan_negzero(i32 %c) { 539; CHECK-LABEL: @fabs_select_negnan_negzero( 540; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 541; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float -0.000000e+00 542; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) 543; CHECK-NEXT: ret float [[FABS]] 544; 545 %cmp = icmp eq i32 %c, 0 546 %select = select i1 %cmp, float 0xFFF8000000000000, float -0.0 547 %fabs = call float @llvm.fabs.f32(float %select) 548 ret float %fabs 549} 550 551define <2 x float> @fabs_select_negnan_negzero_vector(i32 %c) { 552; CHECK-LABEL: @fabs_select_negnan_negzero_vector( 553; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 554; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> splat (float 0xFFF8000000000000), <2 x float> splat (float -0.000000e+00) 555; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]]) 556; CHECK-NEXT: ret <2 x float> [[FABS]] 557; 558 %cmp = icmp eq i32 %c, 0 559 %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float -0.0, float -0.0> 560 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 561 ret <2 x float> %fabs 562} 563 564define float @fabs_select_negnan_zero(i32 %c) { 565; CHECK-LABEL: @fabs_select_negnan_zero( 566; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 567; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float 0.000000e+00 568; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) 569; CHECK-NEXT: ret float [[FABS]] 570; 571 %cmp = icmp eq i32 %c, 0 572 %select = select i1 %cmp, float 0xFFF8000000000000, float 0.0 573 %fabs = call float @llvm.fabs.f32(float %select) 574 ret float %fabs 575} 576 577define <2 x float> @fabs_select_negnan_zero_vector(i32 %c) { 578; CHECK-LABEL: @fabs_select_negnan_zero_vector( 579; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 580; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> splat (float 0xFFF8000000000000), <2 x float> zeroinitializer 581; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]]) 582; CHECK-NEXT: ret <2 x float> [[FABS]] 583; 584 %cmp = icmp eq i32 %c, 0 585 %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0.0, float 0.0> 586 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 587 ret <2 x float> %fabs 588} 589 590; The fabs can't be eliminated because llvm.sqrt.f32 may return -0 or NaN with 591; an arbitrary sign bit. 592define float @fabs_sqrt(float %a) { 593; CHECK-LABEL: @fabs_sqrt( 594; CHECK-NEXT: [[SQRT:%.*]] = call float @llvm.sqrt.f32(float [[A:%.*]]) 595; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]]) 596; CHECK-NEXT: ret float [[FABS]] 597; 598 %sqrt = call float @llvm.sqrt.f32(float %a) 599 %fabs = call float @llvm.fabs.f32(float %sqrt) 600 ret float %fabs 601} 602 603; The fabs can't be eliminated because the nnan sqrt may still return -0. 604define float @fabs_sqrt_nnan(float %a) { 605; CHECK-LABEL: @fabs_sqrt_nnan( 606; CHECK-NEXT: [[SQRT:%.*]] = call nnan float @llvm.sqrt.f32(float [[A:%.*]]) 607; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]]) 608; CHECK-NEXT: ret float [[FABS]] 609; 610 %sqrt = call nnan float @llvm.sqrt.f32(float %a) 611 %fabs = call float @llvm.fabs.f32(float %sqrt) 612 ret float %fabs 613} 614 615; The fabs can't be eliminated because the nsz sqrt may still return NaN. 616define float @fabs_sqrt_nsz(float %a) { 617; CHECK-LABEL: @fabs_sqrt_nsz( 618; CHECK-NEXT: [[SQRT:%.*]] = call nsz float @llvm.sqrt.f32(float [[A:%.*]]) 619; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]]) 620; CHECK-NEXT: ret float [[FABS]] 621; 622 %sqrt = call nsz float @llvm.sqrt.f32(float %a) 623 %fabs = call float @llvm.fabs.f32(float %sqrt) 624 ret float %fabs 625} 626 627; The fabs can be eliminated because we're nsz and nnan. 628define float @fabs_sqrt_nnan_nsz(float %a) { 629; CHECK-LABEL: @fabs_sqrt_nnan_nsz( 630; CHECK-NEXT: [[SQRT:%.*]] = call nnan nsz float @llvm.sqrt.f32(float [[A:%.*]]) 631; CHECK-NEXT: ret float [[SQRT]] 632; 633 %sqrt = call nnan nsz float @llvm.sqrt.f32(float %a) 634 %fabs = call float @llvm.fabs.f32(float %sqrt) 635 ret float %fabs 636} 637 638; The second fabs can be eliminated because the operand to sqrt cannot be -0. 639define float @fabs_sqrt_nnan_fabs(float %a) { 640; CHECK-LABEL: @fabs_sqrt_nnan_fabs( 641; CHECK-NEXT: [[B:%.*]] = call float @llvm.fabs.f32(float [[A:%.*]]) 642; CHECK-NEXT: [[SQRT:%.*]] = call nnan float @llvm.sqrt.f32(float [[B]]) 643; CHECK-NEXT: ret float [[SQRT]] 644; 645 %b = call float @llvm.fabs.f32(float %a) 646 %sqrt = call nnan float @llvm.sqrt.f32(float %b) 647 %fabs = call float @llvm.fabs.f32(float %sqrt) 648 ret float %fabs 649} 650 651define float @fabs_select_positive_constants_vector_extract(i32 %c) { 652; CHECK-LABEL: @fabs_select_positive_constants_vector_extract( 653; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 654; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> splat (float 1.000000e+00), <2 x float> splat (float 2.000000e+00) 655; CHECK-NEXT: [[EXTRACT:%.*]] = extractelement <2 x float> [[SELECT]], i32 0 656; CHECK-NEXT: ret float [[EXTRACT]] 657; 658 %cmp = icmp eq i32 %c, 0 659 %select = select i1 %cmp, <2 x float> <float 1.0, float 1.0>, <2 x float> <float 2.0, float 2.0> 660 %extract = extractelement <2 x float> %select, i32 0 661 %fabs = call float @llvm.fabs.f32(float %extract) 662 ret float %fabs 663} 664 665; Y - (Y - X) --> X 666 667define float @fsub_fsub_common_op(float %x, float %y) { 668; CHECK-LABEL: @fsub_fsub_common_op( 669; CHECK-NEXT: ret float [[X:%.*]] 670; 671 %s = fsub float %y, %x 672 %r = fsub reassoc nsz float %y, %s 673 ret float %r 674} 675 676define <2 x float> @fsub_fsub_common_op_vec(<2 x float> %x, <2 x float> %y) { 677; CHECK-LABEL: @fsub_fsub_common_op_vec( 678; CHECK-NEXT: ret <2 x float> [[X:%.*]] 679; 680 %s = fsub <2 x float> %y, %x 681 %r = fsub reassoc nsz <2 x float> %y, %s 682 ret <2 x float> %r 683} 684 685; Negative test - fsub is not commutative. 686; Y - (X - Y) --> (Y - X) + Y (canonicalized) 687 688define float @fsub_fsub_wrong_common_op(float %x, float %y) { 689; CHECK-LABEL: @fsub_fsub_wrong_common_op( 690; CHECK-NEXT: [[S:%.*]] = fsub float [[X:%.*]], [[Y:%.*]] 691; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz float [[Y]], [[S]] 692; CHECK-NEXT: ret float [[R]] 693; 694 %s = fsub float %x, %y 695 %r = fsub reassoc nsz float %y, %s 696 ret float %r 697} 698 699; Negative test - negated operand needed. 700; (Y - X) - Y --> -X 701 702define float @fsub_fsub_common_op_wrong_commute(float %x, float %y) { 703; CHECK-LABEL: @fsub_fsub_common_op_wrong_commute( 704; CHECK-NEXT: [[S:%.*]] = fsub float [[Y:%.*]], [[X:%.*]] 705; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz float [[S]], [[Y]] 706; CHECK-NEXT: ret float [[R]] 707; 708 %s = fsub float %y, %x 709 %r = fsub reassoc nsz float %s, %y 710 ret float %r 711} 712 713; Negative test - fsub is not commutative. 714; (X - Y) - Y --> ? 715 716define float @fsub_fsub_wrong_common_op_wrong_commute(float %x, float %y) { 717; CHECK-LABEL: @fsub_fsub_wrong_common_op_wrong_commute( 718; CHECK-NEXT: [[S:%.*]] = fsub float [[X:%.*]], [[Y:%.*]] 719; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz float [[S]], [[Y]] 720; CHECK-NEXT: ret float [[R]] 721; 722 %s = fsub float %x, %y 723 %r = fsub reassoc nsz float %s, %y 724 ret float %r 725} 726 727; (Y + X) - Y --> X 728 729define float @fadd_fsub_common_op(float %x, float %y) { 730; CHECK-LABEL: @fadd_fsub_common_op( 731; CHECK-NEXT: ret float [[X:%.*]] 732; 733 %a = fadd float %y, %x 734 %r = fsub reassoc nsz float %a, %y 735 ret float %r 736} 737 738; (X + Y) - Y --> X 739 740define <2 x float> @fadd_fsub_common_op_commute_vec(<2 x float> %x, <2 x float> %y) { 741; CHECK-LABEL: @fadd_fsub_common_op_commute_vec( 742; CHECK-NEXT: ret <2 x float> [[X:%.*]] 743; 744 %a = fadd <2 x float> %x, %y 745 %r = fsub reassoc nsz <2 x float> %a, %y 746 ret <2 x float> %r 747} 748 749; Negative test - negated operand needed. 750; Y - (Y + X) --> -X 751 752define float @fadd_fsub_common_op_wrong_commute(float %x, float %y) { 753; CHECK-LABEL: @fadd_fsub_common_op_wrong_commute( 754; CHECK-NEXT: [[A:%.*]] = fadd float [[Y:%.*]], [[X:%.*]] 755; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz float [[Y]], [[A]] 756; CHECK-NEXT: ret float [[R]] 757; 758 %a = fadd float %y, %x 759 %r = fsub reassoc nsz float %y, %a 760 ret float %r 761} 762 763; Negative test - negated operand needed. 764; Y - (X + Y) --> -X 765 766define float @fadd_fsub_common_op_wrong_commute_commute(float %x, float %y) { 767; CHECK-LABEL: @fadd_fsub_common_op_wrong_commute_commute( 768; CHECK-NEXT: [[A:%.*]] = fadd float [[X:%.*]], [[Y:%.*]] 769; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz float [[Y]], [[A]] 770; CHECK-NEXT: ret float [[R]] 771; 772 %a = fadd float %x, %y 773 %r = fsub reassoc nsz float %y, %a 774 ret float %r 775} 776 777; Y + (X - Y) --> X 778 779define <2 x float> @fsub_fadd_common_op_vec(<2 x float> %x, <2 x float> %y) { 780; CHECK-LABEL: @fsub_fadd_common_op_vec( 781; CHECK-NEXT: ret <2 x float> [[X:%.*]] 782; 783 %s = fsub <2 x float> %x, %y 784 %r = fadd reassoc nsz <2 x float> %y, %s 785 ret <2 x float> %r 786} 787 788; (X - Y) + Y --> X 789 790define float @fsub_fadd_common_op_commute(float %x, float %y) { 791; CHECK-LABEL: @fsub_fadd_common_op_commute( 792; CHECK-NEXT: ret float [[X:%.*]] 793; 794 %s = fsub float %x, %y 795 %r = fadd reassoc nsz float %s, %y 796 ret float %r 797} 798 799; Negative test. 800; Y + (Y - X) --> ? 801 802define float @fsub_fadd_common_op_wrong_commute(float %x, float %y) { 803; CHECK-LABEL: @fsub_fadd_common_op_wrong_commute( 804; CHECK-NEXT: [[S:%.*]] = fsub float [[Y:%.*]], [[X:%.*]] 805; CHECK-NEXT: [[R:%.*]] = fadd reassoc nsz float [[Y]], [[S]] 806; CHECK-NEXT: ret float [[R]] 807; 808 %s = fsub float %y, %x 809 %r = fadd reassoc nsz float %y, %s 810 ret float %r 811} 812 813; Negative test. 814; (Y - X) + Y --> ? 815 816define float @fsub_fadd_common_op_wrong_commute_commute(float %x, float %y) { 817; CHECK-LABEL: @fsub_fadd_common_op_wrong_commute_commute( 818; CHECK-NEXT: [[S:%.*]] = fsub float [[Y:%.*]], [[X:%.*]] 819; CHECK-NEXT: [[R:%.*]] = fadd reassoc nsz float [[S]], [[Y]] 820; CHECK-NEXT: ret float [[R]] 821; 822 %s = fsub float %y, %x 823 %r = fadd reassoc nsz float %s, %y 824 ret float %r 825} 826 827; PR46627 - https://bugs.llvm.org/show_bug.cgi?id=46627 828 829define float @maxnum_with_poszero_op(float %a) { 830; CHECK-LABEL: @maxnum_with_poszero_op( 831; CHECK-NEXT: [[MAX:%.*]] = call float @llvm.maxnum.f32(float [[A:%.*]], float 0.000000e+00) 832; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]]) 833; CHECK-NEXT: ret float [[FABS]] 834; 835 %max = call float @llvm.maxnum.f32(float %a, float 0.0) 836 %fabs = call float @llvm.fabs.f32(float %max) 837 ret float %fabs 838} 839 840define float @maxnum_with_poszero_op_commute(float %a) { 841; CHECK-LABEL: @maxnum_with_poszero_op_commute( 842; CHECK-NEXT: [[SQRT:%.*]] = call float @llvm.sqrt.f32(float [[A:%.*]]) 843; CHECK-NEXT: [[MAX:%.*]] = call float @llvm.maxnum.f32(float 0.000000e+00, float [[SQRT]]) 844; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]]) 845; CHECK-NEXT: ret float [[FABS]] 846; 847 %sqrt = call float @llvm.sqrt.f32(float %a) 848 %max = call float @llvm.maxnum.f32(float 0.0, float %sqrt) 849 %fabs = call float @llvm.fabs.f32(float %max) 850 ret float %fabs 851} 852 853define float @maxnum_with_negzero_op(float %a) { 854; CHECK-LABEL: @maxnum_with_negzero_op( 855; CHECK-NEXT: [[NNAN:%.*]] = call nnan float @llvm.sqrt.f32(float [[A:%.*]]) 856; CHECK-NEXT: [[FABSA:%.*]] = call float @llvm.fabs.f32(float [[NNAN]]) 857; CHECK-NEXT: [[MAX:%.*]] = call float @llvm.maxnum.f32(float -0.000000e+00, float [[FABSA]]) 858; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]]) 859; CHECK-NEXT: ret float [[FABS]] 860; 861 %nnan = call nnan float @llvm.sqrt.f32(float %a) 862 %fabsa = call float @llvm.fabs.f32(float %nnan) 863 %max = call float @llvm.maxnum.f32(float -0.0, float %fabsa) 864 %fabs = call float @llvm.fabs.f32(float %max) 865 ret float %fabs 866} 867 868define float @maxnum_with_negzero_op_commute(float %a) { 869; CHECK-LABEL: @maxnum_with_negzero_op_commute( 870; CHECK-NEXT: [[NNAN:%.*]] = call nnan float @llvm.sqrt.f32(float [[A:%.*]]) 871; CHECK-NEXT: [[FABSA:%.*]] = call float @llvm.fabs.f32(float [[NNAN]]) 872; CHECK-NEXT: [[MAX:%.*]] = call float @llvm.maxnum.f32(float [[FABSA]], float -0.000000e+00) 873; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]]) 874; CHECK-NEXT: ret float [[FABS]] 875; 876 %nnan = call nnan float @llvm.sqrt.f32(float %a) 877 %fabsa = call float @llvm.fabs.f32(float %nnan) 878 %max = call float @llvm.maxnum.f32(float %fabsa, float -0.0) 879 %fabs = call float @llvm.fabs.f32(float %max) 880 ret float %fabs 881} 882 883; If an operand is strictly greater than 0.0, we know the sign of the result of maxnum. 884 885define float @maxnum_with_pos_one_op(float %a) { 886; CHECK-LABEL: @maxnum_with_pos_one_op( 887; CHECK-NEXT: [[MAX:%.*]] = call float @llvm.maxnum.f32(float [[A:%.*]], float 1.000000e+00) 888; CHECK-NEXT: ret float [[MAX]] 889; 890 %max = call float @llvm.maxnum.f32(float %a, float 1.0) 891 %fabs = call float @llvm.fabs.f32(float %max) 892 ret float %fabs 893} 894 895define double @fadd_nnan_inf_op0(double %x) { 896; CHECK-LABEL: @fadd_nnan_inf_op0( 897; CHECK-NEXT: ret double 0x7FF0000000000000 898; 899 %r = fadd nnan double 0x7ff0000000000000, %x 900 ret double %r 901} 902 903define double @fadd_nnan_inf_op1(double %x) { 904; CHECK-LABEL: @fadd_nnan_inf_op1( 905; CHECK-NEXT: ret double 0x7FF0000000000000 906; 907 %r = fadd nnan double %x, 0x7ff0000000000000 908 ret double %r 909} 910 911define <2 x double> @fadd_nnan_neginf_op1(<2 x double> %x) { 912; CHECK-LABEL: @fadd_nnan_neginf_op1( 913; CHECK-NEXT: ret <2 x double> <double 0xFFF0000000000000, double poison> 914; 915 %r = fadd nnan <2 x double> %x, <double 0xfff0000000000000, double poison> 916 ret <2 x double> %r 917} 918 919define double @fadd_nnan_neginf_op0(double %x) { 920; CHECK-LABEL: @fadd_nnan_neginf_op0( 921; CHECK-NEXT: ret double 0xFFF0000000000000 922; 923 %r = fadd nnan double 0xfff0000000000000, %x 924 ret double %r 925} 926 927; negative test - requires nnan 928 929define double @fadd_inf_op0(double %x) { 930; CHECK-LABEL: @fadd_inf_op0( 931; CHECK-NEXT: [[R:%.*]] = fadd double 0x7FF0000000000000, [[X:%.*]] 932; CHECK-NEXT: ret double [[R]] 933; 934 %r = fadd double 0x7ff0000000000000, %x 935 ret double %r 936} 937 938define double @fsub_nnan_inf_op0(double %x) { 939; CHECK-LABEL: @fsub_nnan_inf_op0( 940; CHECK-NEXT: ret double 0x7FF0000000000000 941; 942 %r = fsub nnan double 0x7ff0000000000000, %x 943 ret double %r 944} 945 946; flip sign 947 948define double @fsub_nnan_inf_op1(double %x) { 949; CHECK-LABEL: @fsub_nnan_inf_op1( 950; CHECK-NEXT: ret double 0xFFF0000000000000 951; 952 %r = fsub nnan double %x, 0x7ff0000000000000 953 ret double %r 954} 955 956define <2 x double> @fsub_nnan_inf_op1_vec(<2 x double> %x) { 957; CHECK-LABEL: @fsub_nnan_inf_op1_vec( 958; CHECK-NEXT: ret <2 x double> <double 0x7FF0000000000000, double poison> 959; 960 %r = fsub nnan <2 x double> %x, <double 0xfff0000000000000, double poison> 961 ret <2 x double> %r 962} 963 964define <2 x double> @fsub_nnan_neginf_op0(<2 x double> %x) { 965; CHECK-LABEL: @fsub_nnan_neginf_op0( 966; CHECK-NEXT: ret <2 x double> <double 0xFFF0000000000000, double poison> 967; 968 %r = fsub nnan <2 x double> <double 0xfff0000000000000, double poison>, %x 969 ret <2 x double> %r 970} 971 972; flip sign 973 974define double @fsub_nnan_neginf_op1(double %x) { 975; CHECK-LABEL: @fsub_nnan_neginf_op1( 976; CHECK-NEXT: ret double 0x7FF0000000000000 977; 978 %r = fsub nnan double %x, 0xfff0000000000000 979 ret double %r 980} 981 982; negative test - requires nnan 983 984define double @fsub_inf_op0(double %x) { 985; CHECK-LABEL: @fsub_inf_op0( 986; CHECK-NEXT: [[R:%.*]] = fsub double 0x7FF0000000000000, [[X:%.*]] 987; CHECK-NEXT: ret double [[R]] 988; 989 %r = fsub double 0x7ff0000000000000, %x 990 ret double %r 991} 992 993define i1 @canonicalize_known_positive(float %a) { 994; CHECK-LABEL: @canonicalize_known_positive( 995; CHECK-NEXT: ret i1 true 996; 997 %fabs = call float @llvm.fabs.f32(float %a) 998 %known.positive = call float @llvm.canonicalize.f32(float %fabs) 999 %cmp = fcmp nnan oge float %known.positive, 0.0 1000 ret i1 %cmp 1001} 1002 1003define i1 @canonicalize_unknown_positive(float %unknown) { 1004; CHECK-LABEL: @canonicalize_unknown_positive( 1005; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan oge float [[UNKNOWN:%.*]], 0.000000e+00 1006; CHECK-NEXT: ret i1 [[CMP]] 1007; 1008 %cmp = fcmp nnan oge float %unknown, 0.0 1009 ret i1 %cmp 1010} 1011 1012define i1 @arithmetic_fence_known_positive(float %a) { 1013; CHECK-LABEL: @arithmetic_fence_known_positive( 1014; CHECK-NEXT: ret i1 true 1015; 1016 %fabs = call float @llvm.fabs.f32(float %a) 1017 %known.positive = call float @llvm.arithmetic.fence.f32(float %fabs) 1018 %cmp = fcmp nnan oge float %known.positive, 0.0 1019 ret i1 %cmp 1020} 1021 1022define i1 @arithmetic_fence_unknown_positive(float %unknown) { 1023; CHECK-LABEL: @arithmetic_fence_unknown_positive( 1024; CHECK-NEXT: [[KNOWN_POSITIVE:%.*]] = call float @llvm.arithmetic.fence.f32(float [[UNKNOWN:%.*]]) 1025; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan oge float [[KNOWN_POSITIVE]], 0.000000e+00 1026; CHECK-NEXT: ret i1 [[CMP]] 1027; 1028 %known.positive = call float @llvm.arithmetic.fence.f32(float %unknown) 1029 %cmp = fcmp nnan oge float %known.positive, 0.0 1030 ret i1 %cmp 1031} 1032 1033define i1 @copysign_known_positive_maybe_neg0(float %unknown, float %sign) { 1034; CHECK-LABEL: @copysign_known_positive_maybe_neg0( 1035; CHECK-NEXT: [[SQRT:%.*]] = call nnan ninf float @llvm.sqrt.f32(float [[SIGN:%.*]]) 1036; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[UNKNOWN:%.*]], float [[SQRT]]) 1037; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan oge float [[COPYSIGN]], 0.000000e+00 1038; CHECK-NEXT: ret i1 [[CMP]] 1039; 1040 %sqrt = call ninf nnan float @llvm.sqrt.f32(float %sign) 1041 %copysign = call float @llvm.copysign.f32(float %unknown, float %sqrt) 1042 %cmp = fcmp nnan oge float %copysign, 0.0 1043 ret i1 %cmp 1044} 1045 1046define i1 @copysign_known_positive(float %unknown, float %sign) { 1047; CHECK-LABEL: @copysign_known_positive( 1048; CHECK-NEXT: ret i1 true 1049; 1050 %sqrt = call ninf nnan nsz float @llvm.sqrt.f32(float %sign) 1051 %copysign = call float @llvm.copysign.f32(float %unknown, float %sqrt) 1052 %cmp = fcmp nnan oge float %copysign, 0.0 1053 ret i1 %cmp 1054} 1055 1056define i1 @copysign_unknown_positive(float %unknown, float %unknown.sign) { 1057; CHECK-LABEL: @copysign_unknown_positive( 1058; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[UNKNOWN:%.*]], float [[UNKNOWN_SIGN:%.*]]) 1059; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan oge float [[COPYSIGN]], 0.000000e+00 1060; CHECK-NEXT: ret i1 [[CMP]] 1061; 1062 %copysign = call float @llvm.copysign.f32(float %unknown, float %unknown.sign) 1063 %cmp = fcmp nnan oge float %copysign, 0.0 1064 ret i1 %cmp 1065} 1066 1067; https://alive2.llvm.org/ce/z/Y-EyY3 1068define i1 @floor_known_positive(float %a) { 1069; CHECK-LABEL: @floor_known_positive( 1070; CHECK-NEXT: ret i1 true 1071; 1072 %fabs = call float @llvm.fabs.f32(float %a) 1073 %known.positive = call float @llvm.floor.f32(float %fabs) 1074 %cmp = fcmp nnan oge float %known.positive, 0.0 1075 ret i1 %cmp 1076} 1077 1078define i1 @floor_unknown_positive(float %unknown) { 1079; CHECK-LABEL: @floor_unknown_positive( 1080; CHECK-NEXT: [[OP:%.*]] = call float @llvm.floor.f32(float [[UNKNOWN:%.*]]) 1081; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan oge float [[OP]], 0.000000e+00 1082; CHECK-NEXT: ret i1 [[CMP]] 1083; 1084 %op = call float @llvm.floor.f32(float %unknown) 1085 %cmp = fcmp nnan oge float %op, 0.0 1086 ret i1 %cmp 1087} 1088 1089; https://alive2.llvm.org/ce/z/3tBUoW 1090define i1 @ceil_known_positive(float %a) { 1091; CHECK-LABEL: @ceil_known_positive( 1092; CHECK-NEXT: ret i1 true 1093; 1094 %fabs = call float @llvm.fabs.f32(float %a) 1095 %known.positive = call float @llvm.ceil.f32(float %fabs) 1096 %cmp = fcmp nnan oge float %known.positive, 0.0 1097 ret i1 %cmp 1098} 1099 1100define i1 @ceil_unknown_positive(float %unknown) { 1101; CHECK-LABEL: @ceil_unknown_positive( 1102; CHECK-NEXT: [[OP:%.*]] = call float @llvm.ceil.f32(float [[UNKNOWN:%.*]]) 1103; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan oge float [[OP]], 0.000000e+00 1104; CHECK-NEXT: ret i1 [[CMP]] 1105; 1106 1107 %op = call float @llvm.ceil.f32(float %unknown) 1108 %cmp = fcmp nnan oge float %op, 0.0 1109 ret i1 %cmp 1110} 1111 1112; https://alive2.llvm.org/ce/z/RbyJPX 1113define i1 @trunc_known_positive(float %a) { 1114; CHECK-LABEL: @trunc_known_positive( 1115; CHECK-NEXT: ret i1 true 1116; 1117 %fabs = call float @llvm.fabs.f32(float %a) 1118 %known.positive = call float @llvm.trunc.f32(float %fabs) 1119 %cmp = fcmp nnan oge float %known.positive, 0.0 1120 ret i1 %cmp 1121} 1122 1123define i1 @trunc_unknown_positive(float %unknown) { 1124; CHECK-LABEL: @trunc_unknown_positive( 1125; CHECK-NEXT: [[OP:%.*]] = call float @llvm.trunc.f32(float [[UNKNOWN:%.*]]) 1126; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan oge float [[OP]], 0.000000e+00 1127; CHECK-NEXT: ret i1 [[CMP]] 1128; 1129 %op = call float @llvm.trunc.f32(float %unknown) 1130 %cmp = fcmp nnan oge float %op, 0.0 1131 ret i1 %cmp 1132} 1133 1134; https://alive2.llvm.org/ce/z/bjC2Jm 1135define i1 @rint_known_positive(float %a) { 1136; CHECK-LABEL: @rint_known_positive( 1137; CHECK-NEXT: ret i1 true 1138; 1139 %fabs = call float @llvm.fabs.f32(float %a) 1140 %known.positive = call float @llvm.rint.f32(float %fabs) 1141 %cmp = fcmp nnan oge float %known.positive, 0.0 1142 ret i1 %cmp 1143} 1144 1145define i1 @rint_unknown_positive(float %unknown) { 1146; CHECK-LABEL: @rint_unknown_positive( 1147; CHECK-NEXT: [[OP:%.*]] = call float @llvm.rint.f32(float [[UNKNOWN:%.*]]) 1148; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan oge float [[OP]], 0.000000e+00 1149; CHECK-NEXT: ret i1 [[CMP]] 1150; 1151 %op = call float @llvm.rint.f32(float %unknown) 1152 %cmp = fcmp nnan oge float %op, 0.0 1153 ret i1 %cmp 1154} 1155 1156; https://alive2.llvm.org/ce/z/dFiL9n 1157define i1 @nearbyint_known_positive(float %a) { 1158; CHECK-LABEL: @nearbyint_known_positive( 1159; CHECK-NEXT: ret i1 true 1160; 1161 %fabs = call float @llvm.fabs.f32(float %a) 1162 %known.positive = call float @llvm.nearbyint.f32(float %fabs) 1163 %cmp = fcmp nnan oge float %known.positive, 0.0 1164 ret i1 %cmp 1165} 1166 1167define i1 @nearbyint_unknown_positive(float %unknown) { 1168; CHECK-LABEL: @nearbyint_unknown_positive( 1169; CHECK-NEXT: [[OP:%.*]] = call float @llvm.nearbyint.f32(float [[UNKNOWN:%.*]]) 1170; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan oge float [[OP]], 0.000000e+00 1171; CHECK-NEXT: ret i1 [[CMP]] 1172; 1173 %op = call float @llvm.nearbyint.f32(float %unknown) 1174 %cmp = fcmp nnan oge float %op, 0.0 1175 ret i1 %cmp 1176} 1177 1178; https://alive2.llvm.org/ce/z/kPhS-d 1179define i1 @round_known_positive(float %a) { 1180; CHECK-LABEL: @round_known_positive( 1181; CHECK-NEXT: ret i1 true 1182; 1183 %fabs = call float @llvm.fabs.f32(float %a) 1184 %known.positive = call float @llvm.round.f32(float %fabs) 1185 %cmp = fcmp nnan oge float %known.positive, 0.0 1186 ret i1 %cmp 1187} 1188 1189define i1 @round_unknown_positive(float %unknown) { 1190; CHECK-LABEL: @round_unknown_positive( 1191; CHECK-NEXT: [[OP:%.*]] = call float @llvm.round.f32(float [[UNKNOWN:%.*]]) 1192; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan oge float [[OP]], 0.000000e+00 1193; CHECK-NEXT: ret i1 [[CMP]] 1194; 1195 %op = call float @llvm.round.f32(float %unknown) 1196 %cmp = fcmp nnan oge float %op, 0.0 1197 ret i1 %cmp 1198} 1199 1200; https://alive2.llvm.org/ce/z/Z_tfsu 1201define i1 @roundeven_known_positive(float %a) { 1202; CHECK-LABEL: @roundeven_known_positive( 1203; CHECK-NEXT: ret i1 true 1204; 1205 %fabs = call float @llvm.fabs.f32(float %a) 1206 %known.positive = call float @llvm.roundeven.f32(float %fabs) 1207 %cmp = fcmp nnan oge float %known.positive, 0.0 1208 ret i1 %cmp 1209} 1210 1211define i1 @roundeven_unknown_positive(float %unknown) { 1212; CHECK-LABEL: @roundeven_unknown_positive( 1213; CHECK-NEXT: [[OP:%.*]] = call float @llvm.roundeven.f32(float [[UNKNOWN:%.*]]) 1214; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan oge float [[OP]], 0.000000e+00 1215; CHECK-NEXT: ret i1 [[CMP]] 1216; 1217 %op = call float @llvm.roundeven.f32(float %unknown) 1218 %cmp = fcmp nnan oge float %op, 0.0 1219 ret i1 %cmp 1220} 1221 1222define i1 @fptrunc_round_known_positive(double %a) { 1223; CHECK-LABEL: @fptrunc_round_known_positive( 1224; CHECK-NEXT: ret i1 true 1225; 1226 %fabs = call double @llvm.fabs.f64(double %a) 1227 %known.positive = call float @llvm.fptrunc.round.f32.f64(double %fabs, metadata !"round.downward") 1228 %cmp = fcmp nnan oge float %known.positive, 0.0 1229 ret i1 %cmp 1230} 1231 1232define i1 @fptrunc_round_unknown_positive(double %unknown) { 1233; CHECK-LABEL: @fptrunc_round_unknown_positive( 1234; CHECK-NEXT: [[OP:%.*]] = call float @llvm.fptrunc.round.f32.f64(double [[UNKNOWN:%.*]], metadata !"round.downward") 1235; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan oge float [[OP]], 0.000000e+00 1236; CHECK-NEXT: ret i1 [[CMP]] 1237; 1238 %op = call float @llvm.fptrunc.round.f32.f64(double %unknown, metadata !"round.downward") 1239 %cmp = fcmp nnan oge float %op, 0.0 1240 ret i1 %cmp 1241} 1242