1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2 2; RUN: opt -S -passes=instcombine < %s | FileCheck %s 3 4declare float @llvm.fabs.f32(float) 5declare float @llvm.copysign.f32(float, float) 6declare void @llvm.assume(i1 noundef) 7declare float @llvm.log2.f32(float) 8declare float @llvm.exp2.f32(float) 9declare float @llvm.trunc.f32(float) 10declare float @llvm.arithmetic.fence.f32(float) 11declare float @llvm.minnum.f32(float, float) 12declare float @llvm.maxnum.f32(float, float) 13 14 15define float @ninf_user_select_inf(i1 %cond, float %x, float %y) { 16; CHECK-LABEL: define float @ninf_user_select_inf 17; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[Y:%.*]]) { 18; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[X]], float 0x7FF0000000000000 19; CHECK-NEXT: [[NINF_USER:%.*]] = fmul ninf float [[Y]], [[SELECT]] 20; CHECK-NEXT: ret float [[NINF_USER]] 21; 22 %select = select i1 %cond, float %x, float 0x7FF0000000000000 23 %ninf.user = fmul ninf float %y, %select 24 ret float %ninf.user 25} 26 27define nofpclass(inf) float @ret_nofpclass_inf_poison() { 28; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf_poison() { 29; CHECK-NEXT: ret float poison 30; 31 ret float poison 32} 33 34define nofpclass(inf) float @ret_nofpclass_inf_undef() { 35; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf_undef() { 36; CHECK-NEXT: ret float undef 37; 38 ret float undef 39} 40 41; Make sure there's no infinite loop 42define nofpclass(all) float @ret_nofpclass_all_var(float %arg) { 43; CHECK-LABEL: define nofpclass(all) float @ret_nofpclass_all_var 44; CHECK-SAME: (float [[ARG:%.*]]) { 45; CHECK-NEXT: ret float poison 46; 47 ret float %arg 48} 49 50; Make sure there's no infinite loop 51define nofpclass(all) <2 x float> @ret_nofpclass_all_var_vector(<2 x float> %arg) { 52; CHECK-LABEL: define nofpclass(all) <2 x float> @ret_nofpclass_all_var_vector 53; CHECK-SAME: (<2 x float> [[ARG:%.*]]) { 54; CHECK-NEXT: ret <2 x float> poison 55; 56 ret <2 x float> %arg 57} 58 59define nofpclass(inf) float @ret_nofpclass_inf__0() { 60; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__0() { 61; CHECK-NEXT: ret float 0.000000e+00 62; 63 ret float 0.0 64} 65 66define nofpclass(inf) float @ret_nofpclass_inf__pinf() { 67; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__pinf() { 68; CHECK-NEXT: ret float poison 69; 70 ret float 0x7FF0000000000000 71} 72 73define nofpclass(pinf) float @ret_nofpclass_pinf__pinf() { 74; CHECK-LABEL: define nofpclass(pinf) float @ret_nofpclass_pinf__pinf() { 75; CHECK-NEXT: ret float poison 76; 77 ret float 0x7FF0000000000000 78} 79 80define nofpclass(pinf) float @ret_nofpclass_pinf__ninf() { 81; CHECK-LABEL: define nofpclass(pinf) float @ret_nofpclass_pinf__ninf() { 82; CHECK-NEXT: ret float 0xFFF0000000000000 83; 84 ret float 0xFFF0000000000000 85} 86 87define nofpclass(inf) float @ret_nofpclass_inf__ninf() { 88; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__ninf() { 89; CHECK-NEXT: ret float poison 90; 91 ret float 0xFFF0000000000000 92} 93 94; Basic aggregate tests to ensure this does not crash. 95define nofpclass(nan) { float } @ret_nofpclass_struct_ty() { 96; CHECK-LABEL: define nofpclass(nan) { float } @ret_nofpclass_struct_ty() { 97; CHECK-NEXT: entry: 98; CHECK-NEXT: ret { float } zeroinitializer 99; 100entry: 101 ret { float } zeroinitializer 102} 103 104define nofpclass(nan) { float, float } @ret_nofpclass_multiple_elems_struct_ty() { 105; CHECK-LABEL: define nofpclass(nan) { float, float } @ret_nofpclass_multiple_elems_struct_ty() { 106; CHECK-NEXT: entry: 107; CHECK-NEXT: ret { float, float } zeroinitializer 108; 109entry: 110 ret { float, float } zeroinitializer 111} 112 113define nofpclass(nan) { <4 x float>, <4 x float> } @ret_nofpclass_vector_elems_struct_ty() { 114; CHECK-LABEL: define nofpclass(nan) { <4 x float>, <4 x float> } @ret_nofpclass_vector_elems_struct_ty() { 115; CHECK-NEXT: entry: 116; CHECK-NEXT: ret { <4 x float>, <4 x float> } zeroinitializer 117; 118entry: 119 ret { <4 x float>, <4 x float> } zeroinitializer 120} 121 122define nofpclass(nan) [ 5 x float ] @ret_nofpclass_array_ty() { 123; CHECK-LABEL: define nofpclass(nan) [5 x float] @ret_nofpclass_array_ty() { 124; CHECK-NEXT: entry: 125; CHECK-NEXT: ret [5 x float] zeroinitializer 126; 127entry: 128 ret [ 5 x float ] zeroinitializer 129} 130 131define nofpclass(nan) [ 2 x [ 5 x float ]] @ret_nofpclass_nested_array_ty() { 132; CHECK-LABEL: define nofpclass(nan) [2 x [5 x float]] @ret_nofpclass_nested_array_ty() { 133; CHECK-NEXT: entry: 134; CHECK-NEXT: ret [2 x [5 x float]] zeroinitializer 135; 136entry: 137 ret [ 2 x [ 5 x float ]] zeroinitializer 138} 139 140define nofpclass(pinf) { float } @ret_nofpclass_struct_ty_pinf__ninf() { 141; CHECK-LABEL: define nofpclass(pinf) { float } @ret_nofpclass_struct_ty_pinf__ninf() { 142; CHECK-NEXT: entry: 143; CHECK-NEXT: ret { float } { float 0xFFF0000000000000 } 144; 145entry: 146 ret { float } { float 0xFFF0000000000000 } 147} 148 149define nofpclass(pinf) { float, float } @ret_nofpclass_multiple_elems_struct_ty_pinf__ninf() { 150; CHECK-LABEL: define nofpclass(pinf) { float, float } @ret_nofpclass_multiple_elems_struct_ty_pinf__ninf() { 151; CHECK-NEXT: entry: 152; CHECK-NEXT: ret { float, float } { float 0xFFF0000000000000, float 0xFFF0000000000000 } 153; 154entry: 155 ret { float, float } { float 0xFFF0000000000000, float 0xFFF0000000000000 } 156} 157 158define nofpclass(pinf) { <2 x float> } @ret_nofpclass_vector_elems_struct_ty_pinf__ninf() { 159; CHECK-LABEL: define nofpclass(pinf) { <2 x float> } @ret_nofpclass_vector_elems_struct_ty_pinf__ninf() { 160; CHECK-NEXT: entry: 161; CHECK-NEXT: ret { <2 x float> } { <2 x float> splat (float 0xFFF0000000000000) } 162; 163entry: 164 ret { <2 x float>} { <2 x float> <float 0xFFF0000000000000, float 0xFFF0000000000000> } 165} 166 167; UTC_ARGS: --disable 168; FileCheck does not like the nested square brackets. 169define nofpclass(pinf) [ 1 x [ 1 x float ]] @ret_nofpclass_nested_array_ty_pinf__ninf() { 170; CHECK-LABEL: @ret_nofpclass_nested_array_ty_pinf__ninf() { 171; CHECK-NEXT: entry: 172; CHECK-NEXT: ret {{.*}}float 0xFFF0000000000000 173; 174entry: 175 ret [ 1 x [ 1 x float ]] [[ 1 x float ] [float 0xFFF0000000000000]] 176} 177; UTC_ARGS: --enable 178 179define nofpclass(pzero) { float, float } @ret_nofpclass_multiple_elems_struct_ty_pzero__nzero() { 180; CHECK-LABEL: define nofpclass(pzero) { float, float } @ret_nofpclass_multiple_elems_struct_ty_pzero__nzero() { 181; CHECK-NEXT: entry: 182; CHECK-NEXT: ret { float, float } { float -0.000000e+00, float -0.000000e+00 } 183; 184entry: 185 ret { float, float } { float -0.0, float -0.0 } 186} 187 188define nofpclass(ninf) { float, float } @ret_nofpclass_multiple_elems_struct_ty_ninf__npinf() { 189; CHECK-LABEL: define nofpclass(ninf) { float, float } @ret_nofpclass_multiple_elems_struct_ty_ninf__npinf() { 190; CHECK-NEXT: entry: 191; CHECK-NEXT: ret { float, float } { float 0x7FF0000000000000, float 0x7FF0000000000000 } 192; 193entry: 194 ret { float, float } { float 0x7FF0000000000000, float 0x7FF0000000000000 } 195} 196 197; FIXME (should be poison): Support computeKnownFPClass() for non-zero aggregates. 198define nofpclass(inf) { float, float } @ret_nofpclass_multiple_elems_struct_ty_inf__npinf() { 199; CHECK-LABEL: define nofpclass(inf) { float, float } @ret_nofpclass_multiple_elems_struct_ty_inf__npinf() { 200; CHECK-NEXT: entry: 201; CHECK-NEXT: ret { float, float } { float 0x7FF0000000000000, float 0x7FF0000000000000 } 202; 203entry: 204 ret { float, float } { float 0x7FF0000000000000, float 0x7FF0000000000000 } 205} 206 207; FIXME (should be poison): Support computeKnownFPClass() for non-zero aggregates. 208define nofpclass(nzero) [ 1 x float ] @ret_nofpclass_multiple_elems_struct_ty_nzero_nzero() { 209; CHECK-LABEL: define nofpclass(nzero) [1 x float] @ret_nofpclass_multiple_elems_struct_ty_nzero_nzero() { 210; CHECK-NEXT: entry: 211; CHECK-NEXT: ret [1 x float] [float -0.000000e+00] 212; 213entry: 214 ret [ 1 x float ] [ float -0.0 ] 215} 216 217; Negative test, do nothing 218define nofpclass(inf) float @ret_nofpclass_inf__select_nofpclass_inf_lhs(i1 %cond, float nofpclass(inf) %x, float %y) { 219; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_nofpclass_inf_lhs 220; CHECK-SAME: (i1 [[COND:%.*]], float nofpclass(inf) [[X:%.*]], float [[Y:%.*]]) { 221; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[X]], float [[Y]] 222; CHECK-NEXT: ret float [[SELECT]] 223; 224 %select = select i1 %cond, float %x, float %y 225 ret float %select 226} 227 228; Make sure nofpclass from source argument is used, fold to %y 229define nofpclass(inf) float @ret_nofpclass_inf__select_nofpclass_arg_only_inf_lhs(i1 %cond, float nofpclass(nan norm zero sub) %x, float %y) { 230; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_nofpclass_arg_only_inf_lhs 231; CHECK-SAME: (i1 [[COND:%.*]], float nofpclass(nan zero sub norm) [[X:%.*]], float [[Y:%.*]]) { 232; CHECK-NEXT: ret float [[Y]] 233; 234 %select = select i1 %cond, float %x, float %y 235 ret float %select 236} 237 238; Make sure nofpclass from source argument is used, fold to %x 239define nofpclass(inf) float @ret_nofpclass_inf__select_nofpclass_arg_only_inf_rhs(i1 %cond, float %x, float nofpclass(nan norm zero sub) %y) { 240; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_nofpclass_arg_only_inf_rhs 241; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float nofpclass(nan zero sub norm) [[Y:%.*]]) { 242; CHECK-NEXT: ret float [[X]] 243; 244 %select = select i1 %cond, float %x, float %y 245 ret float %select 246} 247 248; Fold to ret %y 249define nofpclass(inf) [3 x [2 x float]] @ret_float_array(i1 %cond, [3 x [2 x float]] nofpclass(nan norm zero sub) %x, [3 x [2 x float]] %y) { 250; CHECK-LABEL: define nofpclass(inf) [3 x [2 x float]] @ret_float_array 251; CHECK-SAME: (i1 [[COND:%.*]], [3 x [2 x float]] nofpclass(nan zero sub norm) [[X:%.*]], [3 x [2 x float]] [[Y:%.*]]) { 252; CHECK-NEXT: ret [3 x [2 x float]] [[Y]] 253; 254 %select = select i1 %cond, [3 x [2 x float]] %x, [3 x [2 x float]] %y 255 ret [3 x [2 x float ]] %select 256} 257 258; Fold to ret %x 259define nofpclass(inf) float @ret_nofpclass_inf__select_pinf_lhs(i1 %cond, float %x) { 260; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_pinf_lhs 261; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) { 262; CHECK-NEXT: ret float [[X]] 263; 264 %select = select i1 %cond, float 0x7FF0000000000000, float %x 265 ret float %select 266} 267 268; Fold to ret %x 269define nofpclass(inf) float @ret_nofpclass_inf__select_pinf_rhs(i1 %cond, float %x) { 270; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_pinf_rhs 271; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) { 272; CHECK-NEXT: ret float [[X]] 273; 274 %select = select i1 %cond, float %x, float 0x7FF0000000000000 275 ret float %select 276} 277 278; Fold to poison 279define nofpclass(inf) float @ret_nofpclass_inf__select_pinf_or_ninf(i1 %cond, float %x) { 280; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_pinf_or_ninf 281; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) { 282; CHECK-NEXT: ret float poison 283; 284 %select = select i1 %cond, float 0x7FF0000000000000, float 0xFFF0000000000000 285 ret float %select 286} 287 288; Fold to poison 289define nofpclass(inf) float @ret_nofpclass_inf__select_ninf_or_pinf(i1 %cond, float %x) { 290; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_ninf_or_pinf 291; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) { 292; CHECK-NEXT: ret float poison 293; 294 %select = select i1 %cond, float 0xFFF0000000000000, float 0x7FF0000000000000 295 ret float %select 296} 297 298; Fold to pos inf 299define nofpclass(ninf) float @ret_nofpclass_ninf__select_ninf_or_pinf(i1 %cond, float %x) { 300; CHECK-LABEL: define nofpclass(ninf) float @ret_nofpclass_ninf__select_ninf_or_pinf 301; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) { 302; CHECK-NEXT: ret float 0x7FF0000000000000 303; 304 %select = select i1 %cond, float 0xFFF0000000000000, float 0x7FF0000000000000 305 ret float %select 306} 307 308; Fold to neg inf 309define nofpclass(pinf) float @ret_nofpclass_pinf__select_ninf_or_pinf(i1 %cond, float %x) { 310; CHECK-LABEL: define nofpclass(pinf) float @ret_nofpclass_pinf__select_ninf_or_pinf 311; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) { 312; CHECK-NEXT: ret float 0xFFF0000000000000 313; 314 %select = select i1 %cond, float 0xFFF0000000000000, float 0x7FF0000000000000 315 ret float %select 316} 317 318; Fold to poison 319define nofpclass(zero) float @ret_nofpclass_zero__select_pzero_or_nzero(i1 %cond, float %x) { 320; CHECK-LABEL: define nofpclass(zero) float @ret_nofpclass_zero__select_pzero_or_nzero 321; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) { 322; CHECK-NEXT: ret float poison 323; 324 %select = select i1 %cond, float 0.0, float -0.0 325 ret float %select 326} 327 328; Fold to +0 329define nofpclass(nzero) float @ret_nofpclass_nzero__select_pzero_or_nzero(i1 %cond, float %x) { 330; CHECK-LABEL: define nofpclass(nzero) float @ret_nofpclass_nzero__select_pzero_or_nzero 331; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) { 332; CHECK-NEXT: ret float 0.000000e+00 333; 334 %select = select i1 %cond, float 0.0, float -0.0 335 ret float %select 336} 337 338; Fold to -0 339define nofpclass(pzero) float @ret_nofpclass_pzero__select_pzero_or_nzero(i1 %cond, float %x) { 340; CHECK-LABEL: define nofpclass(pzero) float @ret_nofpclass_pzero__select_pzero_or_nzero 341; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) { 342; CHECK-NEXT: ret float -0.000000e+00 343; 344 %select = select i1 %cond, float 0.0, float -0.0 345 ret float %select 346} 347 348; Fold to ret %x 349define nofpclass(inf) <2 x float> @ret_nofpclass_inf__select_pinf_lhs_vector(<2 x i1> %cond, <2 x float> %x) { 350; CHECK-LABEL: define nofpclass(inf) <2 x float> @ret_nofpclass_inf__select_pinf_lhs_vector 351; CHECK-SAME: (<2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]]) { 352; CHECK-NEXT: ret <2 x float> [[X]] 353; 354 %select = select <2 x i1> %cond, <2 x float> <float 0x7FF0000000000000, float 0x7FF0000000000000>, <2 x float> %x 355 ret <2 x float> %select 356} 357 358; Fold to ret %x 359define nofpclass(inf) <2 x float> @ret_nofpclass_inf__select_pinf_lhs_vector_undef(<2 x i1> %cond, <2 x float> %x) { 360; CHECK-LABEL: define nofpclass(inf) <2 x float> @ret_nofpclass_inf__select_pinf_lhs_vector_undef 361; CHECK-SAME: (<2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]]) { 362; CHECK-NEXT: ret <2 x float> [[X]] 363; 364 %select = select <2 x i1> %cond, <2 x float> <float 0x7FF0000000000000, float poison>, <2 x float> %x 365 ret <2 x float> %select 366} 367 368; Fold to ret %x 369define nofpclass(inf) <2 x float> @ret_nofpclass_inf__select_mixed_inf_lhs_vector(<2 x i1> %cond, <2 x float> %x) { 370; CHECK-LABEL: define nofpclass(inf) <2 x float> @ret_nofpclass_inf__select_mixed_inf_lhs_vector 371; CHECK-SAME: (<2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]]) { 372; CHECK-NEXT: ret <2 x float> [[X]] 373; 374 %select = select <2 x i1> %cond, <2 x float> <float 0x7FF0000000000000, float 0xFFF0000000000000>, <2 x float> %x 375 ret <2 x float> %select 376} 377 378; Can't delete the select 379define nofpclass(inf) float @ret_nofpclass_inf__select_multi_use_pinf_lhs(i1 %cond, float %x, ptr %ptr) { 380; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_multi_use_pinf_lhs 381; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], ptr [[PTR:%.*]]) { 382; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float 0x7FF0000000000000, float [[X]] 383; CHECK-NEXT: store float [[SELECT]], ptr [[PTR]], align 4 384; CHECK-NEXT: ret float [[SELECT]] 385; 386 %select = select i1 %cond, float 0x7FF0000000000000, float %x 387 store float %select, ptr %ptr 388 ret float %select 389} 390 391; Can't do anything 392define nofpclass(inf) float @ret_nofpclass_inf__select_p0_lhs(i1 %cond, float %x) { 393; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_p0_lhs 394; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) { 395; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float 0.000000e+00, float [[X]] 396; CHECK-NEXT: ret float [[SELECT]] 397; 398 %select = select i1 %cond, float 0.0, float %x 399 ret float %select 400} 401 402; Can't do anything 403define nofpclass(inf) float @ret_nofpclass_inf__select_p0_rhs(i1 %cond, float %x) { 404; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_p0_rhs 405; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) { 406; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[X]], float 0.000000e+00 407; CHECK-NEXT: ret float [[SELECT]] 408; 409 %select = select i1 %cond, float %x, float 0.0 410 ret float %select 411} 412 413; Can't do anything 414define nofpclass(nan) float @ret_nofpclass_nan__select_pinf_lhs(i1 %cond, float %x) { 415; CHECK-LABEL: define nofpclass(nan) float @ret_nofpclass_nan__select_pinf_lhs 416; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) { 417; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float 0x7FF0000000000000, float [[X]] 418; CHECK-NEXT: ret float [[SELECT]] 419; 420 %select = select i1 %cond, float 0x7FF0000000000000, float %x 421 ret float %select 422} 423 424; Can't do anything 425define nofpclass(nan) float @ret_nofpclass_nan__select_pinf_rhs(i1 %cond, float %x) { 426; CHECK-LABEL: define nofpclass(nan) float @ret_nofpclass_nan__select_pinf_rhs 427; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) { 428; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[X]], float 0x7FF0000000000000 429; CHECK-NEXT: ret float [[SELECT]] 430; 431 %select = select i1 %cond, float %x, float 0x7FF0000000000000 432 ret float %select 433} 434 435define nofpclass(inf nan) float @ret_nofpclass_inf_nan__select_chain_inf_nan_0(i1 %cond, float %x) { 436; CHECK-LABEL: define nofpclass(nan inf) float @ret_nofpclass_inf_nan__select_chain_inf_nan_0 437; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) { 438; CHECK-NEXT: ret float [[X]] 439; 440 %select0 = select i1 %cond, float 0x7FF8000000000000, float %x 441 %select1 = select i1 %cond, float 0x7FF0000000000000, float %select0 442 ret float %select1 443} 444 445define nofpclass(inf nan) float @ret_nofpclass_inf_nan__select_chain_inf_nan_1(i1 %cond, float %x) { 446; CHECK-LABEL: define nofpclass(nan inf) float @ret_nofpclass_inf_nan__select_chain_inf_nan_1 447; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) { 448; CHECK-NEXT: ret float poison 449; 450 %select0 = select i1 %cond, float %x, float 0x7FF8000000000000 451 %select1 = select i1 %cond, float 0x7FF0000000000000, float %select0 452 ret float %select1 453} 454 455define nofpclass(nan) float @ret_nofpclass_nan__select_chain_inf_nan(i1 %cond, float %x) { 456; CHECK-LABEL: define nofpclass(nan) float @ret_nofpclass_nan__select_chain_inf_nan 457; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) { 458; CHECK-NEXT: [[SELECT1:%.*]] = select i1 [[COND]], float 0x7FF0000000000000, float [[X]] 459; CHECK-NEXT: ret float [[SELECT1]] 460; 461 %select0 = select i1 %cond, float 0x7FF8000000000000, float %x 462 %select1 = select i1 %cond, float 0x7FF0000000000000, float %select0 463 ret float %select1 464} 465 466define nofpclass(inf) float @ret_nofpclass_inf__select_chain_inf_nan_0(i1 %cond, float %x) { 467; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_chain_inf_nan_0 468; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) { 469; CHECK-NEXT: ret float [[X]] 470; 471 %select0 = select i1 %cond, float 0x7FF8000000000000, float %x 472 %select1 = select i1 %cond, float 0x7FF0000000000000, float %select0 473 ret float %select1 474} 475 476define nofpclass(inf) float @ret_nofpclass_inf__select_chain_inf_nan_1(i1 %cond, float %x) { 477; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_chain_inf_nan_1 478; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) { 479; CHECK-NEXT: ret float 0x7FF8000000000000 480; 481 %select0 = select i1 %cond, float 0x7FF8000000000000, float %x 482 %select1 = select i1 %cond, float %select0, float 0x7FF0000000000000 483 ret float %select1 484} 485 486; Simplify to fabs %x 487define nofpclass(inf) float @ret_nofpclass_inf__fabs_select_ninf_rhs(i1 %cond, float %x) { 488; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__fabs_select_ninf_rhs 489; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) { 490; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]]) 491; CHECK-NEXT: ret float [[TMP1]] 492; 493 %select = select i1 %cond, float %x, float 0xFFF0000000000000 494 %fabs = call float @llvm.fabs.f32(float %select) 495 ret float %fabs 496} 497 498; Simplify to fabs %x 499define nofpclass(inf) float @ret_nofpclass_inf__fabs_select_pinf_rhs(i1 %cond, float %x) { 500; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__fabs_select_pinf_rhs 501; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) { 502; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]]) 503; CHECK-NEXT: ret float [[TMP1]] 504; 505 %select = select i1 %cond, float %x, float 0x7FF0000000000000 506 %fabs = call float @llvm.fabs.f32(float %select) 507 ret float %fabs 508} 509 510define nofpclass(ninf nnorm nsub nzero) float @ret_nofpclass_no_negatives__fabs_select_pinf_rhs(i1 %cond, float %x) { 511; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_nofpclass_no_negatives__fabs_select_pinf_rhs 512; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) { 513; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]]) 514; CHECK-NEXT: [[FABS:%.*]] = select i1 [[COND]], float [[TMP1]], float 0x7FF0000000000000 515; CHECK-NEXT: ret float [[FABS]] 516; 517 %select = select i1 %cond, float %x, float 0x7FF0000000000000 518 %fabs = call float @llvm.fabs.f32(float %select) 519 ret float %fabs 520} 521 522; Fold to fabs(%x), preserving a possible nan's payload bits 523define nofpclass(pinf pnorm psub pzero) float @ret_nofpclass_no_positives__fabs_select_pinf_rhs(i1 %cond, float %x) { 524; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_nofpclass_no_positives__fabs_select_pinf_rhs 525; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) { 526; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]]) 527; CHECK-NEXT: ret float [[TMP1]] 528; 529 %select = select i1 %cond, float %x, float 0x7FF0000000000000 530 %fabs = call float @llvm.fabs.f32(float %select) 531 ret float %fabs 532} 533 534define nofpclass(nan ninf nnorm nsub nzero) float @ret_nofpclass_no_negatives_nan__fabs_select_pinf_rhs(i1 %cond, float %x) { 535; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @ret_nofpclass_no_negatives_nan__fabs_select_pinf_rhs 536; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) { 537; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]]) 538; CHECK-NEXT: [[FABS:%.*]] = select i1 [[COND]], float [[TMP1]], float 0x7FF0000000000000 539; CHECK-NEXT: ret float [[FABS]] 540; 541 %select = select i1 %cond, float %x, float 0x7FF0000000000000 542 %fabs = call float @llvm.fabs.f32(float %select) 543 ret float %fabs 544} 545 546; Can fold to poison 547define nofpclass(nan pinf pnorm psub pzero) float @ret_nofpclass_no_positives_nan__fabs_select_pinf_rhs(i1 %cond, float %x) { 548; CHECK-LABEL: define nofpclass(nan pinf pzero psub pnorm) float @ret_nofpclass_no_positives_nan__fabs_select_pinf_rhs 549; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) { 550; CHECK-NEXT: ret float poison 551; 552 %select = select i1 %cond, float %x, float 0x7FF0000000000000 553 %fabs = call float @llvm.fabs.f32(float %select) 554 ret float %fabs 555} 556 557; Simplify to fneg %x 558define nofpclass(inf) float @ret_nofpclass_inf__fneg_select_ninf_rhs(i1 %cond, float %x) { 559; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__fneg_select_ninf_rhs 560; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) { 561; CHECK-NEXT: [[X_NEG:%.*]] = fneg float [[X]] 562; CHECK-NEXT: ret float [[X_NEG]] 563; 564 %select = select i1 %cond, float %x, float 0xFFF0000000000000 565 %fneg = fneg float %select 566 ret float %fneg 567} 568 569; Simplify to fneg %x 570define nofpclass(inf nnorm nsub nzero) float @ret_nofpclass_nonegatives_noinf___fneg_select_pinf_rhs(i1 %cond, float %x) { 571; CHECK-LABEL: define nofpclass(inf nzero nsub nnorm) float @ret_nofpclass_nonegatives_noinf___fneg_select_pinf_rhs 572; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) { 573; CHECK-NEXT: [[X_NEG:%.*]] = fneg float [[X]] 574; CHECK-NEXT: ret float [[X_NEG]] 575; 576 %select = select i1 %cond, float %x, float 0x7FF0000000000000 577 %fneg = fneg float %select 578 ret float %fneg 579} 580 581; Simplify to fneg %x 582define nofpclass(inf nnorm nsub nzero) float @ret_nofpclass_nonegatives_noinf___fneg_select_ninf_lhs(i1 %cond, float %x) { 583; CHECK-LABEL: define nofpclass(inf nzero nsub nnorm) float @ret_nofpclass_nonegatives_noinf___fneg_select_ninf_lhs 584; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) { 585; CHECK-NEXT: [[X_NEG:%.*]] = fneg float [[X]] 586; CHECK-NEXT: ret float [[X_NEG]] 587; 588 %select = select i1 %cond, float 0xFFF0000000000000, float %x 589 %fneg = fneg float %select 590 ret float %fneg 591} 592 593define nofpclass(pzero psub pnorm pinf) float @ret_nofpclass_nopositives___fneg_select_pinf_rhs(i1 %cond, float %x) { 594; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_nofpclass_nopositives___fneg_select_pinf_rhs 595; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) { 596; CHECK-NEXT: [[X_NEG:%.*]] = fneg float [[X]] 597; CHECK-NEXT: [[FNEG:%.*]] = select i1 [[COND]], float [[X_NEG]], float 0xFFF0000000000000 598; CHECK-NEXT: ret float [[FNEG]] 599; 600 %select = select i1 %cond, float %x, float 0x7FF0000000000000 601 %fneg = fneg float %select 602 ret float %fneg 603} 604 605; Fold to fneg fabs 606define nofpclass(inf) float @ret_nofpclass_inf__fneg_fabs_select_pinf_rhs(i1 %cond, float %x) { 607; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__fneg_fabs_select_pinf_rhs 608; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) { 609; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]]) 610; CHECK-NEXT: [[DOTNEG:%.*]] = fneg float [[TMP1]] 611; CHECK-NEXT: ret float [[DOTNEG]] 612; 613 %select = select i1 %cond, float %x, float 0x7FF0000000000000 614 %fabs = call float @llvm.fabs.f32(float %select) 615 %fneg = fneg float %fabs 616 ret float %fneg 617} 618 619; Fold to fneg fabs, may need to preserve a nan payload 620define nofpclass(ninf nnorm nsub nzero) float @ret_nofpclass_nonegatives__fneg_fabs_select_pinf_rhs(i1 %cond, float %x) { 621; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_nofpclass_nonegatives__fneg_fabs_select_pinf_rhs 622; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) { 623; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]]) 624; CHECK-NEXT: [[DOTNEG:%.*]] = fneg float [[TMP1]] 625; CHECK-NEXT: ret float [[DOTNEG]] 626; 627 %select = select i1 %cond, float %x, float 0x7FF0000000000000 628 %fabs = call float @llvm.fabs.f32(float %select) 629 %fneg = fneg float %fabs 630 ret float %fneg 631} 632 633 634; Fold to poison 635define nofpclass(nan ninf nnorm nsub nzero) float @ret_nofpclass_nonegatives_nonan__fneg_fabs_select_pinf_rhs(i1 %cond, float %x) { 636; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @ret_nofpclass_nonegatives_nonan__fneg_fabs_select_pinf_rhs 637; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) { 638; CHECK-NEXT: ret float poison 639; 640 %select = select i1 %cond, float %x, float 0x7FF0000000000000 641 %fabs = call float @llvm.fabs.f32(float %select) 642 %fneg = fneg float %fabs 643 ret float %fneg 644} 645 646; should fold to ret copysign(%x) 647define nofpclass(inf) float @ret_nofpclass_inf__copysign_unknown_select_pinf_rhs(i1 %cond, float %x, float %unknown.sign) { 648; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__copysign_unknown_select_pinf_rhs 649; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) { 650; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[X]], float [[UNKNOWN_SIGN]]) 651; CHECK-NEXT: ret float [[COPYSIGN]] 652; 653 %select = select i1 %cond, float %x, float 0x7FF0000000000000 654 %copysign = call float @llvm.copysign.f32(float %select, float %unknown.sign) 655 ret float %copysign 656} 657 658define nofpclass(inf) float @ret_nofpclass_inf__copysign_positive_select_pinf_rhs(i1 %cond, float %x) { 659; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__copysign_positive_select_pinf_rhs 660; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) { 661; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]]) 662; CHECK-NEXT: ret float [[TMP1]] 663; 664 %select = select i1 %cond, float %x, float 0x7FF0000000000000 665 %copysign = call float @llvm.copysign.f32(float %select, float 1.0) 666 ret float %copysign 667} 668 669define nofpclass(inf) float @ret_nofpclass_inf__copysign_negative_select_pinf_rhs(i1 %cond, float %x) { 670; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__copysign_negative_select_pinf_rhs 671; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) { 672; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]]) 673; CHECK-NEXT: [[DOTNEG:%.*]] = fneg float [[TMP1]] 674; CHECK-NEXT: ret float [[DOTNEG]] 675; 676 %select = select i1 %cond, float %x, float 0x7FF0000000000000 677 %copysign = call float @llvm.copysign.f32(float %select, float -1.0) 678 ret float %copysign 679} 680 681; can fold to fneg(fabs(x)) 682define nofpclass(pinf pnorm psub pzero) float @ret_nofpclass_nopositives_copysign(float %x, float %unknown.sign) { 683; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_nofpclass_nopositives_copysign 684; CHECK-SAME: (float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) { 685; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]]) 686; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg float [[TMP1]] 687; CHECK-NEXT: ret float [[COPYSIGN]] 688; 689 %copysign = call float @llvm.copysign.f32(float %x, float %unknown.sign) 690 ret float %copysign 691} 692 693; can fold to fneg(fabs(x)) 694define nofpclass(pinf pnorm psub pzero) float @ret_nofpclass_nopositives_copysign_nnan_flag(float %x, float %unknown.sign) { 695; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_nofpclass_nopositives_copysign_nnan_flag 696; CHECK-SAME: (float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) { 697; CHECK-NEXT: [[TMP1:%.*]] = call nnan float @llvm.fabs.f32(float [[X]]) 698; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg nnan float [[TMP1]] 699; CHECK-NEXT: ret float [[COPYSIGN]] 700; 701 %copysign = call nnan float @llvm.copysign.f32(float %x, float %unknown.sign) 702 ret float %copysign 703} 704 705; can fold to fneg(fabs(x)) 706define nofpclass(nan pinf pnorm psub pzero) float @ret_nofpclass_nopositives_nonan_copysign(float %x, float %unknown.sign) { 707; CHECK-LABEL: define nofpclass(nan pinf pzero psub pnorm) float @ret_nofpclass_nopositives_nonan_copysign 708; CHECK-SAME: (float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) { 709; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]]) 710; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg float [[TMP1]] 711; CHECK-NEXT: ret float [[COPYSIGN]] 712; 713 %copysign = call float @llvm.copysign.f32(float %x, float %unknown.sign) 714 ret float %copysign 715} 716 717; can fold to fabs(x) 718define nofpclass(ninf nnorm nsub nzero) float @ret_nofpclass_nonegatives_copysign(float %x, float %unknown.sign) { 719; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_nofpclass_nonegatives_copysign 720; CHECK-SAME: (float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) { 721; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.fabs.f32(float [[X]]) 722; CHECK-NEXT: ret float [[COPYSIGN]] 723; 724 %copysign = call float @llvm.copysign.f32(float %x, float %unknown.sign) 725 ret float %copysign 726} 727 728; can fold to fabs(x) 729define nofpclass(ninf nnorm nsub nzero) float @ret_nofpclass_nonegatives_copysign_nnan_flag(float %x, float %unknown.sign) { 730; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_nofpclass_nonegatives_copysign_nnan_flag 731; CHECK-SAME: (float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) { 732; CHECK-NEXT: [[COPYSIGN:%.*]] = call nnan float @llvm.fabs.f32(float [[X]]) 733; CHECK-NEXT: ret float [[COPYSIGN]] 734; 735 %copysign = call nnan float @llvm.copysign.f32(float %x, float %unknown.sign) 736 ret float %copysign 737} 738 739; can fold to fabs(x) 740define nofpclass(nan ninf nnorm nsub nzero) float @ret_nofpclass_nonegatives_nonan_copysign(float %x, float %unknown.sign) { 741; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @ret_nofpclass_nonegatives_nonan_copysign 742; CHECK-SAME: (float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) { 743; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.fabs.f32(float [[X]]) 744; CHECK-NEXT: ret float [[COPYSIGN]] 745; 746 %copysign = call float @llvm.copysign.f32(float %x, float %unknown.sign) 747 ret float %copysign 748} 749 750define nofpclass(pinf pnorm psub pzero) float @ret_nofpclass_nopositives__copysign_fabs_select_pinf_rhs(i1 %cond, float %x, float %sign) { 751; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_nofpclass_nopositives__copysign_fabs_select_pinf_rhs 752; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[SIGN:%.*]]) { 753; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]]) 754; CHECK-NEXT: ret float [[TMP1]] 755; 756 %select = select i1 %cond, float %x, float 0x7FF0000000000000 757 %fabs.sign = call float @llvm.fabs.f32(float %sign) 758 %copysign = call float @llvm.copysign.f32(float %select, float %fabs.sign) 759 ret float %copysign 760} 761 762; Can fold to copysign %x 763define nofpclass(inf nnorm nsub nzero) float @ret_nofpclass_no_negatives_noinf__copysign_unknown_select_pinf_rhs(i1 %cond, float %x, float %unknown.sign) { 764; CHECK-LABEL: define nofpclass(inf nzero nsub nnorm) float @ret_nofpclass_no_negatives_noinf__copysign_unknown_select_pinf_rhs 765; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) { 766; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.fabs.f32(float [[X]]) 767; CHECK-NEXT: ret float [[COPYSIGN]] 768; 769 %select = select i1 %cond, float %x, float 0x7FF0000000000000 770 %copysign = call float @llvm.copysign.f32(float %select, float %unknown.sign) 771 ret float %copysign 772} 773 774; Can fold to copysign %x 775define nofpclass(inf pnorm psub pzero) float @ret_nofpclass_no_positives_noinf__copysign_unknown_select_pinf_rhs(i1 %cond, float %x, float %unknown.sign) { 776; CHECK-LABEL: define nofpclass(inf pzero psub pnorm) float @ret_nofpclass_no_positives_noinf__copysign_unknown_select_pinf_rhs 777; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) { 778; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]]) 779; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg float [[TMP1]] 780; CHECK-NEXT: ret float [[COPYSIGN]] 781; 782 %select = select i1 %cond, float %x, float 0x7FF0000000000000 783 %copysign = call float @llvm.copysign.f32(float %select, float %unknown.sign) 784 ret float %copysign 785} 786 787; Can't fold because it could have nan payload bits 788define nofpclass(ninf nnorm nsub nzero) float @ret_nofpclass_no_negatives__copysign_unknown_select_pinf_rhs(i1 %cond, float %x, float %unknown.sign) { 789; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_nofpclass_no_negatives__copysign_unknown_select_pinf_rhs 790; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) { 791; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]]) 792; CHECK-NEXT: [[COPYSIGN:%.*]] = select i1 [[COND]], float [[TMP1]], float 0x7FF0000000000000 793; CHECK-NEXT: ret float [[COPYSIGN]] 794; 795 %select = select i1 %cond, float %x, float 0x7FF0000000000000 796 %copysign = call float @llvm.copysign.f32(float %select, float %unknown.sign) 797 ret float %copysign 798} 799 800; Can't fold because it could be nan 801define nofpclass(pinf pnorm psub pzero) float @ret_nofpclass_no_positives__copysign_unknown_select_pinf_rhs(i1 %cond, float %x, float %unknown.sign) { 802; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_nofpclass_no_positives__copysign_unknown_select_pinf_rhs 803; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) { 804; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]]) 805; CHECK-NEXT: [[DOTNEG:%.*]] = fneg float [[TMP1]] 806; CHECK-NEXT: [[COPYSIGN:%.*]] = select i1 [[COND]], float [[DOTNEG]], float 0xFFF0000000000000 807; CHECK-NEXT: ret float [[COPYSIGN]] 808; 809 %select = select i1 %cond, float %x, float 0x7FF0000000000000 810 %copysign = call float @llvm.copysign.f32(float %select, float %unknown.sign) 811 ret float %copysign 812} 813 814; Could fold to copysign with constant 815define nofpclass(nan ninf nnorm nsub nzero) float @ret_nofpclass_no_negatives_nonan__copysign_unknown_select_pinf_rhs(i1 %cond, float %x, float %unknown.sign) { 816; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @ret_nofpclass_no_negatives_nonan__copysign_unknown_select_pinf_rhs 817; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) { 818; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]]) 819; CHECK-NEXT: [[COPYSIGN:%.*]] = select i1 [[COND]], float [[TMP1]], float 0x7FF0000000000000 820; CHECK-NEXT: ret float [[COPYSIGN]] 821; 822 %select = select i1 %cond, float %x, float 0x7FF0000000000000 823 %copysign = call float @llvm.copysign.f32(float %select, float %unknown.sign) 824 ret float %copysign 825} 826 827; Could fold to copysign %x with constant 828define nofpclass(nan pinf pnorm psub pzero) float @ret_nofpclass_no_positives_nonan__copysign_unknown_select_pinf_rhs(i1 %cond, float %x, float %unknown.sign) { 829; CHECK-LABEL: define nofpclass(nan pinf pzero psub pnorm) float @ret_nofpclass_no_positives_nonan__copysign_unknown_select_pinf_rhs 830; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) { 831; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]]) 832; CHECK-NEXT: [[DOTNEG:%.*]] = fneg float [[TMP1]] 833; CHECK-NEXT: [[COPYSIGN:%.*]] = select i1 [[COND]], float [[DOTNEG]], float 0xFFF0000000000000 834; CHECK-NEXT: ret float [[COPYSIGN]] 835; 836 %select = select i1 %cond, float %x, float 0x7FF0000000000000 837 %copysign = call float @llvm.copysign.f32(float %select, float %unknown.sign) 838 ret float %copysign 839} 840 841; Do nothing 842define nofpclass(ninf nnorm nsub nzero) float @ret_nofpclass_negatives__select_clamp_neg_to_zero(float %x) { 843; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_nofpclass_negatives__select_clamp_neg_to_zero 844; CHECK-SAME: (float [[X:%.*]]) { 845; CHECK-NEXT: [[IS_LT_ZERO:%.*]] = fcmp olt float [[X]], 0.000000e+00 846; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_LT_ZERO]], float 0.000000e+00, float [[X]] 847; CHECK-NEXT: ret float [[SELECT]] 848; 849 %is.lt.zero = fcmp olt float %x, 0.0 850 %select = select i1 %is.lt.zero, float 0.0, float %x 851 ret float %select 852} 853 854; Can fold to ret %x, assumed to be nan 855define nofpclass(ninf nnorm nsub nzero) float @ret_nofpclass_negatives__select_clamp_pos_to_zero(float %x) { 856; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_nofpclass_negatives__select_clamp_pos_to_zero 857; CHECK-SAME: (float [[X:%.*]]) { 858; CHECK-NEXT: [[IS_GT_ZERO:%.*]] = fcmp ogt float [[X]], 0.000000e+00 859; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_GT_ZERO]], float 0.000000e+00, float [[X]] 860; CHECK-NEXT: ret float [[SELECT]] 861; 862 %is.gt.zero = fcmp ogt float %x, 0.0 863 %select = select i1 %is.gt.zero, float 0.0, float %x 864 ret float %select 865} 866 867; Can fold to ret +0 868define nofpclass(nan ninf nnorm nsub nzero) float @ret_nofpclass_nan_negatives__select_clamp_pos_to_zero(float %x) { 869; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @ret_nofpclass_nan_negatives__select_clamp_pos_to_zero 870; CHECK-SAME: (float [[X:%.*]]) { 871; CHECK-NEXT: [[IS_GT_ZERO:%.*]] = fcmp ogt float [[X]], 0.000000e+00 872; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_GT_ZERO]], float 0.000000e+00, float [[X]] 873; CHECK-NEXT: ret float [[SELECT]] 874; 875 %is.gt.zero = fcmp ogt float %x, 0.0 876 %select = select i1 %is.gt.zero, float 0.0, float %x 877 ret float %select 878} 879 880; Can fold to ret poison 881define nofpclass(nan ninf nnorm nsub zero) float @ret_nofpclass_nan_negatives_zero__select_clamp_pos_to_zero(float %x) { 882; CHECK-LABEL: define nofpclass(nan ninf zero nsub nnorm) float @ret_nofpclass_nan_negatives_zero__select_clamp_pos_to_zero 883; CHECK-SAME: (float [[X:%.*]]) { 884; CHECK-NEXT: ret float [[X]] 885; 886 %is.gt.zero = fcmp ogt float %x, 0.0 887 %select = select i1 %is.gt.zero, float 0.0, float %x 888 ret float %select 889} 890 891; Can fold to ret %x, assumed to be nan 892define nofpclass(ninf nnorm nsub zero) float @ret_nofpclass_negatives_zero__select_clamp_pos_to_zero(float %x) { 893; CHECK-LABEL: define nofpclass(ninf zero nsub nnorm) float @ret_nofpclass_negatives_zero__select_clamp_pos_to_zero 894; CHECK-SAME: (float [[X:%.*]]) { 895; CHECK-NEXT: ret float [[X]] 896; 897 %is.gt.zero = fcmp ogt float %x, 0.0 898 %select = select i1 %is.gt.zero, float 0.0, float %x 899 ret float %select 900} 901 902; Assume should allow folding ret %y 903define nofpclass(inf) float @ret_nofpclass_noinfs__assumed_isinf__select_pinf_lhs(i1 %cond, float %x, float %y) { 904; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_noinfs__assumed_isinf__select_pinf_lhs 905; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[Y:%.*]]) { 906; CHECK-NEXT: [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X]]) 907; CHECK-NEXT: [[X_IS_INF:%.*]] = fcmp oeq float [[FABS_X]], 0x7FF0000000000000 908; CHECK-NEXT: call void @llvm.assume(i1 [[X_IS_INF]]) 909; CHECK-NEXT: ret float [[Y]] 910; 911 %fabs.x = call float @llvm.fabs.f32(float %x) 912 %x.is.inf = fcmp oeq float %fabs.x, 0x7FF0000000000000 913 call void @llvm.assume(i1 %x.is.inf) 914 %select = select i1 %cond, float %x, float %y 915 ret float %select 916} 917 918; Ideally should be able to fold out everything after the exp2 call. 919define nofpclass(nan inf nzero nsub nnorm) float @powr_issue64870(float nofpclass(nan inf) %x, float nofpclass(nan inf) %y) { 920; CHECK-LABEL: define nofpclass(nan inf nzero nsub nnorm) float @powr_issue64870 921; CHECK-SAME: (float nofpclass(nan inf) [[X:%.*]], float nofpclass(nan inf) [[Y:%.*]]) { 922; CHECK-NEXT: entry: 923; CHECK-NEXT: [[I:%.*]] = tail call float @llvm.fabs.f32(float [[X]]) 924; CHECK-NEXT: [[I1:%.*]] = tail call float @llvm.log2.f32(float [[I]]) 925; CHECK-NEXT: [[I2:%.*]] = fmul float [[I1]], [[Y]] 926; CHECK-NEXT: [[I3:%.*]] = tail call nofpclass(ninf nzero nsub nnorm) float @llvm.exp2.f32(float [[I2]]) 927; CHECK-NEXT: [[I6:%.*]] = fcmp oeq float [[X]], 0.000000e+00 928; CHECK-NEXT: [[I7:%.*]] = select i1 [[I6]], float 0.000000e+00, float [[I3]] 929; CHECK-NEXT: [[I8:%.*]] = fcmp oeq float [[Y]], 0.000000e+00 930; CHECK-NEXT: [[I11:%.*]] = fcmp oeq float [[X]], 1.000000e+00 931; CHECK-NEXT: [[TMP0:%.*]] = select i1 [[I11]], i1 true, i1 [[I8]] 932; CHECK-NEXT: [[I12:%.*]] = select i1 [[TMP0]], float 1.000000e+00, float [[I7]] 933; CHECK-NEXT: ret float [[I12]] 934; 935entry: 936 %i = tail call float @llvm.fabs.f32(float %x) 937 %i1 = tail call float @llvm.log2.f32(float %i) 938 %i2 = fmul float %i1, %y 939 %i3 = tail call nofpclass(ninf nzero nsub nnorm) float @llvm.exp2.f32(float %i2) 940 %i4 = fcmp olt float %y, 0.000000e+00 941 %i5 = select i1 %i4, float 0x7FF0000000000000, float 0.000000e+00 942 %i6 = fcmp oeq float %x, 0.000000e+00 943 %i7 = select i1 %i6, float %i5, float %i3 944 %i8 = fcmp oeq float %y, 0.000000e+00 945 %i9 = select i1 %i6, float 0x7FF8000000000000, float 1.000000e+00 946 %i10 = select i1 %i8, float %i9, float %i7 947 %i11 = fcmp oeq float %x, 1.000000e+00 948 %i12 = select i1 %i11, float 1.000000e+00, float %i10 949 %i13 = fcmp olt float %x, 0.000000e+00 950 %i14 = select i1 %i13, float 0x7FF8000000000000, float %i12 951 ret float %i14 952} 953 954; Different implementation of powr 955define nofpclass(nan inf nzero nsub nnorm) float @test_powr_issue64870_2(float nofpclass(nan inf) %arg, float nofpclass(nan inf) %arg1) #0 { 956; CHECK-LABEL: define nofpclass(nan inf nzero nsub nnorm) float @test_powr_issue64870_2 957; CHECK-SAME: (float nofpclass(nan inf) [[ARG:%.*]], float nofpclass(nan inf) [[ARG1:%.*]]) { 958; CHECK-NEXT: bb: 959; CHECK-NEXT: [[I:%.*]] = fcmp olt float [[ARG]], 0.000000e+00 960; CHECK-NEXT: [[I2:%.*]] = select i1 [[I]], float 0x7FF8000000000000, float [[ARG]] 961; CHECK-NEXT: [[I3:%.*]] = tail call float @llvm.log2.f32(float noundef [[I2]]) 962; CHECK-NEXT: [[I4:%.*]] = select i1 [[I]], float 0x7FF8000000000000, float [[ARG1]] 963; CHECK-NEXT: [[I5:%.*]] = fmul float [[I4]], [[I3]] 964; CHECK-NEXT: [[I6:%.*]] = tail call noundef nofpclass(ninf nzero nsub nnorm) float @llvm.exp2.f32(float noundef [[I5]]) 965; CHECK-NEXT: [[I10:%.*]] = fcmp oeq float [[I2]], 0.000000e+00 966; CHECK-NEXT: [[I12:%.*]] = select i1 [[I10]], float 0.000000e+00, float [[I6]] 967; CHECK-NEXT: ret float [[I12]] 968; 969bb: 970 %i = fcmp olt float %arg, 0.000000e+00 971 %i2 = select i1 %i, float 0x7FF8000000000000, float %arg 972 %i3 = tail call float @llvm.log2.f32(float noundef %i2) #2 973 %i4 = select i1 %i, float 0x7FF8000000000000, float %arg1 974 %i5 = fmul float %i4, %i3 975 %i6 = tail call noundef nofpclass(ninf nzero nsub nnorm) float @llvm.exp2.f32(float noundef %i5) 976 %i7 = fcmp olt float %i4, 0.000000e+00 977 %i8 = select i1 %i7, float 0x7FF0000000000000, float 0.000000e+00 978 %i9 = fcmp ueq float %i4, 0.000000e+00 979 %i10 = fcmp oeq float %i2, 0.000000e+00 980 %i11 = select i1 %i9, float 0x7FF8000000000000, float %i8 981 %i12 = select i1 %i10, float %i11, float %i6 982 ret float %i12 983} 984 985; implementation of pow with some prunable cases 986define nofpclass(nan inf) float @pow_f32(float nofpclass(nan inf) %arg, float nofpclass(nan inf) %arg1) #0 { 987; CHECK-LABEL: define nofpclass(nan inf) float @pow_f32 988; CHECK-SAME: (float nofpclass(nan inf) [[ARG:%.*]], float nofpclass(nan inf) [[ARG1:%.*]]) { 989; CHECK-NEXT: bb: 990; CHECK-NEXT: [[I:%.*]] = tail call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float noundef [[ARG]]) 991; CHECK-NEXT: [[I2:%.*]] = tail call float @llvm.log2.f32(float noundef [[I]]) 992; CHECK-NEXT: [[I3:%.*]] = fmul float [[I2]], [[ARG1]] 993; CHECK-NEXT: [[I4:%.*]] = tail call noundef float @llvm.exp2.f32(float noundef [[I3]]) 994; CHECK-NEXT: [[I5:%.*]] = tail call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float noundef [[ARG1]]) 995; CHECK-NEXT: [[I6:%.*]] = tail call float @llvm.trunc.f32(float noundef [[I5]]) 996; CHECK-NEXT: [[I7:%.*]] = fcmp oeq float [[I6]], [[I5]] 997; CHECK-NEXT: [[I8:%.*]] = fmul float [[I5]], 5.000000e-01 998; CHECK-NEXT: [[I9:%.*]] = tail call float @llvm.trunc.f32(float noundef [[I8]]) 999; CHECK-NEXT: [[I10:%.*]] = fcmp une float [[I9]], [[I8]] 1000; CHECK-NEXT: [[I11:%.*]] = and i1 [[I7]], [[I10]] 1001; CHECK-NEXT: [[I12:%.*]] = select i1 [[I11]], float [[ARG]], float 1.000000e+00 1002; CHECK-NEXT: [[I13:%.*]] = tail call noundef float @llvm.copysign.f32(float noundef [[I4]], float noundef [[I12]]) 1003; CHECK-NEXT: [[I17:%.*]] = fcmp oeq float [[ARG]], 0.000000e+00 1004; CHECK-NEXT: [[TMP0:%.*]] = tail call nofpclass(nan sub norm) float @llvm.copysign.f32(float 0.000000e+00, float [[ARG]]) 1005; CHECK-NEXT: [[I22:%.*]] = select i1 [[I11]], float [[TMP0]], float 0.000000e+00 1006; CHECK-NEXT: [[I23:%.*]] = select i1 [[I17]], float [[I22]], float [[I13]] 1007; CHECK-NEXT: [[I24:%.*]] = fcmp oeq float [[ARG]], 1.000000e+00 1008; CHECK-NEXT: [[I25:%.*]] = fcmp oeq float [[ARG1]], 0.000000e+00 1009; CHECK-NEXT: [[I26:%.*]] = or i1 [[I24]], [[I25]] 1010; CHECK-NEXT: [[I27:%.*]] = select i1 [[I26]], float 1.000000e+00, float [[I23]] 1011; CHECK-NEXT: ret float [[I27]] 1012; 1013bb: 1014 %i = tail call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float noundef %arg) 1015 %i2 = tail call float @llvm.log2.f32(float noundef %i) 1016 %i3 = fmul float %i2, %arg1 1017 %i4 = tail call noundef float @llvm.exp2.f32(float noundef %i3) 1018 %i5 = tail call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float noundef %arg1) 1019 %i6 = tail call float @llvm.trunc.f32(float noundef %i5) 1020 %i7 = fcmp oeq float %i6, %i5 1021 %i8 = fmul float %i5, 5.000000e-01 1022 %i9 = tail call float @llvm.trunc.f32(float noundef %i8) 1023 %i10 = fcmp une float %i9, %i8 1024 %i11 = and i1 %i7, %i10 1025 %i12 = select i1 %i11, float %arg, float 1.000000e+00 1026 %i13 = tail call noundef float @llvm.copysign.f32(float noundef %i4, float noundef %i12) 1027 %i14 = fcmp olt float %arg, 0.000000e+00 1028 %i15 = select i1 %i7, float %i13, float 0x7FF8000000000000 1029 %i16 = select i1 %i14, float %i15, float %i13 1030 %i17 = fcmp oeq float %arg, 0.000000e+00 1031 %i18 = fcmp olt float %arg1, 0.000000e+00 1032 %i19 = xor i1 %i17, %i18 1033 %i20 = select i1 %i19, float 0.000000e+00, float 0x7FF0000000000000 1034 %i21 = select i1 %i11, float %arg, float 0.000000e+00 1035 %i22 = tail call noundef nofpclass(nan sub norm) float @llvm.copysign.f32(float noundef %i20, float noundef %i21) 1036 %i23 = select i1 %i17, float %i22, float %i16 1037 %i24 = fcmp oeq float %arg, 1.000000e+00 1038 %i25 = fcmp oeq float %arg1, 0.000000e+00 1039 %i26 = or i1 %i24, %i25 1040 %i27 = select i1 %i26, float 1.000000e+00, float %i23 1041 ret float %i27 1042} 1043 1044declare float @extern() 1045 1046; Make sure nofpclass from arbitrary callsite is used, fold to %y 1047define nofpclass(inf) float @ret_nofpclass_inf__select_nofpclass_call_only_inf(i1 %cond, float %y) { 1048; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_nofpclass_call_only_inf 1049; CHECK-SAME: (i1 [[COND:%.*]], float [[Y:%.*]]) { 1050; CHECK-NEXT: [[MUST_BE_INF:%.*]] = call nofpclass(nan zero sub norm) float @extern() 1051; CHECK-NEXT: ret float [[Y]] 1052; 1053 %must.be.inf = call nofpclass(nan norm zero sub) float @extern() 1054 %select = select i1 %cond, float %must.be.inf, float %y 1055 ret float %select 1056} 1057 1058define nofpclass(pinf) float @ret_nofpclass_pinf__nofpclass_call_only_inf(i1 %cond, float %y) { 1059; CHECK-LABEL: define nofpclass(pinf) float @ret_nofpclass_pinf__nofpclass_call_only_inf 1060; CHECK-SAME: (i1 [[COND:%.*]], float [[Y:%.*]]) { 1061; CHECK-NEXT: [[MUST_BE_INF:%.*]] = call nofpclass(nan zero sub norm) float @extern() 1062; CHECK-NEXT: ret float 0xFFF0000000000000 1063; 1064 %must.be.inf = call nofpclass(nan norm zero sub) float @extern() 1065 ret float %must.be.inf 1066} 1067 1068define nofpclass(ninf) float @ret_nofpclass_ninf__nofpclass_call_only_inf(i1 %cond, float %y) { 1069; CHECK-LABEL: define nofpclass(ninf) float @ret_nofpclass_ninf__nofpclass_call_only_inf 1070; CHECK-SAME: (i1 [[COND:%.*]], float [[Y:%.*]]) { 1071; CHECK-NEXT: [[MUST_BE_INF:%.*]] = call nofpclass(nan zero sub norm) float @extern() 1072; CHECK-NEXT: ret float 0x7FF0000000000000 1073; 1074 %must.be.inf = call nofpclass(nan norm zero sub) float @extern() 1075 ret float %must.be.inf 1076} 1077 1078define nofpclass(nzero) float @ret_nofpclass_nzero__nofpclass_call_only_zero(i1 %cond, float %y) { 1079; CHECK-LABEL: define nofpclass(nzero) float @ret_nofpclass_nzero__nofpclass_call_only_zero 1080; CHECK-SAME: (i1 [[COND:%.*]], float [[Y:%.*]]) { 1081; CHECK-NEXT: [[MUST_BE_ZERO:%.*]] = call nofpclass(nan inf sub norm) float @extern() 1082; CHECK-NEXT: ret float 0.000000e+00 1083; 1084 %must.be.zero = call nofpclass(nan sub norm inf) float @extern() 1085 ret float %must.be.zero 1086} 1087 1088define nofpclass(pzero) float @ret_nofpclass_pzero__nofpclass_call_only_zero(i1 %cond, float %y) { 1089; CHECK-LABEL: define nofpclass(pzero) float @ret_nofpclass_pzero__nofpclass_call_only_zero 1090; CHECK-SAME: (i1 [[COND:%.*]], float [[Y:%.*]]) { 1091; CHECK-NEXT: [[MUST_BE_ZERO:%.*]] = call nofpclass(nan inf sub norm) float @extern() 1092; CHECK-NEXT: ret float -0.000000e+00 1093; 1094 %must.be.zero = call nofpclass(nan sub norm inf) float @extern() 1095 ret float %must.be.zero 1096} 1097 1098; Should not fold this, should not assume payload/sign bits are canonical 1099define nofpclass(qnan) float @ret_nofpclass_qnan__nofpclass_call_only_nan(i1 %cond, float %y) { 1100; CHECK-LABEL: define nofpclass(qnan) float @ret_nofpclass_qnan__nofpclass_call_only_nan 1101; CHECK-SAME: (i1 [[COND:%.*]], float [[Y:%.*]]) { 1102; CHECK-NEXT: [[MUST_BE_NAN:%.*]] = call nofpclass(inf zero sub norm) float @extern() 1103; CHECK-NEXT: ret float [[MUST_BE_NAN]] 1104; 1105 %must.be.nan = call nofpclass(inf norm zero sub) float @extern() 1106 ret float %must.be.nan 1107} 1108 1109; Should not fold this, should not assume payload/sign bits are canonical 1110define nofpclass(snan) float @ret_nofpclass_snan__nofpclass_call_only_nan(i1 %cond, float %y) { 1111; CHECK-LABEL: define nofpclass(snan) float @ret_nofpclass_snan__nofpclass_call_only_nan 1112; CHECK-SAME: (i1 [[COND:%.*]], float [[Y:%.*]]) { 1113; CHECK-NEXT: [[MUST_BE_NAN:%.*]] = call nofpclass(inf zero sub norm) float @extern() 1114; CHECK-NEXT: ret float [[MUST_BE_NAN]] 1115; 1116 %must.be.nan = call nofpclass(inf norm zero sub) float @extern() 1117 ret float %must.be.nan 1118} 1119 1120; Assume call should allow folding this to %y 1121; TODO: Not working, multiple user problem. 1122define nofpclass(inf) float @ret_nofpclass_inf__select_assumed_call_result_only_inf(i1 %cond, float %y) { 1123; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_assumed_call_result_only_inf 1124; CHECK-SAME: (i1 [[COND:%.*]], float [[Y:%.*]]) { 1125; CHECK-NEXT: [[MUST_BE_INF:%.*]] = call float @extern() 1126; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MUST_BE_INF]]) 1127; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq float [[FABS]], 0x7FF0000000000000 1128; CHECK-NEXT: call void @llvm.assume(i1 [[IS_INF]]) 1129; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[MUST_BE_INF]], float [[Y]] 1130; CHECK-NEXT: ret float [[SELECT]] 1131; 1132 %must.be.inf = call float @extern() 1133 %fabs = call float @llvm.fabs.f32(float %must.be.inf) 1134 %is.inf = fcmp oeq float %fabs, 0x7FF0000000000000 1135 call void @llvm.assume(i1 %is.inf) 1136 %select = select i1 %cond, float %must.be.inf, float %y 1137 ret float %select 1138} 1139 1140define nofpclass(inf) float @ret_nofpclass_inf__simple_phi_inf_or_unknown(i1 %cond, float %x) { 1141; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__simple_phi_inf_or_unknown 1142; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) { 1143; CHECK-NEXT: entry: 1144; CHECK-NEXT: br i1 [[COND]], label [[BB0:%.*]], label [[RET:%.*]] 1145; CHECK: bb0: 1146; CHECK-NEXT: br label [[RET]] 1147; CHECK: ret: 1148; CHECK-NEXT: [[PHI:%.*]] = phi float [ 0x7FF0000000000000, [[ENTRY:%.*]] ], [ [[X]], [[BB0]] ] 1149; CHECK-NEXT: ret float [[PHI]] 1150; 1151entry: 1152 br i1 %cond, label %bb0, label %ret 1153 1154bb0: 1155 br label %ret 1156 1157ret: 1158 %phi = phi float [ 0x7FF0000000000000, %entry ], [ %x, %bb0 ] 1159 ret float %phi 1160} 1161 1162declare i1 @loop.cond() 1163 1164declare float @loop.func() 1165 1166 1167; Should be able to fold inf initial value to poison 1168define nofpclass(inf) float @ret_nofpclass_inf__phi_0(i1 %cond0, float %unknown) { 1169; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__phi_0 1170; CHECK-SAME: (i1 [[COND0:%.*]], float [[UNKNOWN:%.*]]) { 1171; CHECK-NEXT: entry: 1172; CHECK-NEXT: br i1 [[COND0]], label [[LOOP:%.*]], label [[RET:%.*]] 1173; CHECK: loop: 1174; CHECK-NEXT: [[PHI_LOOP:%.*]] = phi float [ 0x7FF0000000000000, [[ENTRY:%.*]] ], [ [[LOOP_FUNC:%.*]], [[LOOP]] ] 1175; CHECK-NEXT: [[LOOP_FUNC]] = call nofpclass(nan) float @loop.func() 1176; CHECK-NEXT: [[LOOP_COND:%.*]] = call i1 @loop.cond() 1177; CHECK-NEXT: br i1 [[LOOP_COND]], label [[RET]], label [[LOOP]] 1178; CHECK: ret: 1179; CHECK-NEXT: [[PHI_RET:%.*]] = phi float [ 0.000000e+00, [[ENTRY]] ], [ [[PHI_LOOP]], [[LOOP]] ] 1180; CHECK-NEXT: ret float [[PHI_RET]] 1181; 1182entry: 1183 br i1 %cond0, label %loop, label %ret 1184 1185loop: 1186 %phi.loop = phi float [ 0x7FF0000000000000, %entry ], [ %loop.func, %loop ] 1187 %loop.func = call nofpclass(nan) float @loop.func() 1188 %loop.cond = call i1 @loop.cond() 1189 br i1 %loop.cond, label %ret, label %loop 1190 1191ret: 1192 %phi.ret = phi float [ 0.0, %entry ], [ %phi.loop, %loop ] 1193 ret float %phi.ret 1194} 1195 1196; fold to ret 0 1197define nofpclass(inf) float @ret_nofpclass_inf__recursive_phi_0(i1 %cond0, float %unknown) { 1198; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__recursive_phi_0 1199; CHECK-SAME: (i1 [[COND0:%.*]], float [[UNKNOWN:%.*]]) { 1200; CHECK-NEXT: entry: 1201; CHECK-NEXT: br i1 [[COND0]], label [[LOOP:%.*]], label [[RET:%.*]] 1202; CHECK: loop: 1203; CHECK-NEXT: [[LOOP_COND:%.*]] = call i1 @loop.cond() 1204; CHECK-NEXT: br i1 [[LOOP_COND]], label [[RET]], label [[LOOP]] 1205; CHECK: ret: 1206; CHECK-NEXT: ret float 0.000000e+00 1207; 1208entry: 1209 br i1 %cond0, label %loop, label %ret 1210 1211loop: 1212 %phi.loop = phi float [ 0x7FF0000000000000, %entry ], [ %phi.loop, %loop ] 1213 %loop.cond = call i1 @loop.cond() 1214 br i1 %loop.cond, label %ret, label %loop 1215 1216ret: 1217 %phi.ret = phi float [ 0.0, %entry ], [ %phi.loop, %loop ] 1218 ret float %phi.ret 1219} 1220 1221; fold to ret poison 1222define nofpclass(inf) float @ret_nofpclass_inf__recursive_phi_1(i1 %cond0, float %unknown) { 1223; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__recursive_phi_1 1224; CHECK-SAME: (i1 [[COND0:%.*]], float [[UNKNOWN:%.*]]) { 1225; CHECK-NEXT: entry: 1226; CHECK-NEXT: br i1 [[COND0]], label [[LOOP:%.*]], label [[RET:%.*]] 1227; CHECK: loop: 1228; CHECK-NEXT: [[LOOP_COND:%.*]] = call i1 @loop.cond() 1229; CHECK-NEXT: br i1 [[LOOP_COND]], label [[RET]], label [[LOOP]] 1230; CHECK: ret: 1231; CHECK-NEXT: ret float poison 1232; 1233entry: 1234 br i1 %cond0, label %loop, label %ret 1235 1236loop: 1237 %phi.loop = phi float [ 0x7FF0000000000000, %entry ], [ %phi.loop, %loop ] 1238 %loop.cond = call i1 @loop.cond() 1239 br i1 %loop.cond, label %ret, label %loop 1240 1241ret: 1242 %phi.ret = phi float [ 0x7FF0000000000000, %entry ], [ %phi.loop, %loop ] 1243 ret float %phi.ret 1244} 1245 1246; Should be able to fold inf initial values to poison 1247define nofpclass(inf) float @ret_nofpclass_inf__phi_switch_repeated_predecessor(i32 %switch, float %unknown) { 1248; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__phi_switch_repeated_predecessor 1249; CHECK-SAME: (i32 [[SWITCH:%.*]], float [[UNKNOWN:%.*]]) { 1250; CHECK-NEXT: entry: 1251; CHECK-NEXT: switch i32 [[SWITCH]], label [[RET:%.*]] [ 1252; CHECK-NEXT: i32 0, label [[LOOP:%.*]] 1253; CHECK-NEXT: i32 1, label [[LOOP]] 1254; CHECK-NEXT: ] 1255; CHECK: loop: 1256; CHECK-NEXT: [[PHI_LOOP:%.*]] = phi float [ 0x7FF0000000000000, [[ENTRY:%.*]] ], [ 0x7FF0000000000000, [[ENTRY]] ], [ [[UNKNOWN]], [[LOOP]] ] 1257; CHECK-NEXT: [[LOOP_COND:%.*]] = call i1 @loop.cond() 1258; CHECK-NEXT: br i1 [[LOOP_COND]], label [[RET]], label [[LOOP]] 1259; CHECK: ret: 1260; CHECK-NEXT: [[PHI_RET:%.*]] = phi float [ 0.000000e+00, [[ENTRY]] ], [ [[PHI_LOOP]], [[LOOP]] ] 1261; CHECK-NEXT: ret float [[PHI_RET]] 1262; 1263entry: 1264 switch i32 %switch, label %ret [ 1265 i32 0, label %loop 1266 i32 1, label %loop 1267 ] 1268 1269loop: 1270 %phi.loop = phi float [ 0x7FF0000000000000, %entry ], [ 0x7FF0000000000000, %entry ], [ %unknown, %loop ] 1271 %loop.cond = call i1 @loop.cond() 1272 br i1 %loop.cond, label %ret, label %loop 1273 1274ret: 1275 %phi.ret = phi float [ 0.0, %entry ], [ %phi.loop, %loop ] 1276 ret float %phi.ret 1277} 1278 1279; Simplify to arithmetic.fence %x 1280define nofpclass(inf) float @ret_nofpclass_inf__arithmetic_fence_select_pinf_rhs(i1 %cond, float %x) { 1281; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__arithmetic_fence_select_pinf_rhs 1282; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) { 1283; CHECK-NEXT: [[FENCE:%.*]] = call float @llvm.arithmetic.fence.f32(float [[X]]) 1284; CHECK-NEXT: ret float [[FENCE]] 1285; 1286 %select = select i1 %cond, float %x, float 0x7FF0000000000000 1287 %fence = call float @llvm.arithmetic.fence.f32(float %select) 1288 ret float %fence 1289} 1290 1291; Can simplify to %x 1292define nofpclass(pinf) float @ret_nofpclass_pinf__minnum_pinf(i1 %cond, float %x) { 1293; CHECK-LABEL: define nofpclass(pinf) float @ret_nofpclass_pinf__minnum_pinf 1294; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) { 1295; CHECK-NEXT: [[MIN:%.*]] = call float @llvm.minnum.f32(float [[X]], float 0x7FF0000000000000) 1296; CHECK-NEXT: ret float [[MIN]] 1297; 1298 %min = call float @llvm.minnum.f32(float %x, float 0x7FF0000000000000) 1299 ret float %min 1300} 1301 1302; Can fold to -inf 1303define nofpclass(pinf) float @ret_nofpclass_pinf__minnum_ninf(i1 %cond, float %x) { 1304; CHECK-LABEL: define nofpclass(pinf) float @ret_nofpclass_pinf__minnum_ninf 1305; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) { 1306; CHECK-NEXT: ret float 0xFFF0000000000000 1307; 1308 %min = call float @llvm.minnum.f32(float %x, float 0xFFF0000000000000) 1309 ret float %min 1310} 1311 1312; Can simplify to %x 1313define nofpclass(ninf) float @ret_nofpclass_ninf__maxnum_ninf(i1 %cond, float %x) { 1314; CHECK-LABEL: define nofpclass(ninf) float @ret_nofpclass_ninf__maxnum_ninf 1315; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) { 1316; CHECK-NEXT: [[MAX:%.*]] = call float @llvm.maxnum.f32(float [[X]], float 0xFFF0000000000000) 1317; CHECK-NEXT: ret float [[MAX]] 1318; 1319 %max = call float @llvm.maxnum.f32(float %x, float 0xFFF0000000000000) 1320 ret float %max 1321} 1322 1323; Can fold to +inf 1324define nofpclass(ninf) float @ret_nofpclass_ninf__maxnum_pinf(i1 %cond, float %x) { 1325; CHECK-LABEL: define nofpclass(ninf) float @ret_nofpclass_ninf__maxnum_pinf 1326; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) { 1327; CHECK-NEXT: ret float 0x7FF0000000000000 1328; 1329 %max = call float @llvm.maxnum.f32(float %x, float 0x7FF0000000000000) 1330 ret float %max 1331} 1332