1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -mtriple=x86_64-unknown-linux-gnu < %s -passes=instcombine -S | FileCheck %s 3 4; Make sure libcalls are replaced with intrinsic calls. 5 6declare float @llvm.fabs.f32(float) 7declare <2 x float> @llvm.fabs.v2f32(<2 x float>) 8declare double @llvm.fabs.f64(double) 9declare fp128 @llvm.fabs.f128(fp128) 10 11declare float @fabsf(float) 12declare double @fabs(double) 13declare fp128 @fabsl(fp128) 14declare float @llvm.fma.f32(float, float, float) 15declare float @llvm.fmuladd.f32(float, float, float) 16 17declare void @use(float) 18declare void @usebool(i1) 19 20define float @replace_fabs_call_f32(float %x) { 21; CHECK-LABEL: @replace_fabs_call_f32( 22; CHECK-NEXT: [[FABSF:%.*]] = tail call float @llvm.fabs.f32(float [[X:%.*]]) 23; CHECK-NEXT: ret float [[FABSF]] 24; 25 %fabsf = tail call float @fabsf(float %x) 26 ret float %fabsf 27} 28 29define double @replace_fabs_call_f64(double %x) { 30; CHECK-LABEL: @replace_fabs_call_f64( 31; CHECK-NEXT: [[FABS:%.*]] = tail call double @llvm.fabs.f64(double [[X:%.*]]) 32; CHECK-NEXT: ret double [[FABS]] 33; 34 %fabs = tail call double @fabs(double %x) 35 ret double %fabs 36} 37 38define fp128 @replace_fabs_call_f128(fp128 %x) { 39; CHECK-LABEL: @replace_fabs_call_f128( 40; CHECK-NEXT: [[FABSL:%.*]] = tail call fp128 @llvm.fabs.f128(fp128 [[X:%.*]]) 41; CHECK-NEXT: ret fp128 [[FABSL]] 42; 43 %fabsl = tail call fp128 @fabsl(fp128 %x) 44 ret fp128 %fabsl 45} 46 47; Make sure fast math flags are preserved when replacing the libcall. 48define float @fmf_replace_fabs_call_f32(float %x) { 49; CHECK-LABEL: @fmf_replace_fabs_call_f32( 50; CHECK-NEXT: [[FABSF:%.*]] = tail call nnan float @llvm.fabs.f32(float [[X:%.*]]) 51; CHECK-NEXT: ret float [[FABSF]] 52; 53 %fabsf = tail call nnan float @fabsf(float %x) 54 ret float %fabsf 55} 56 57; Make sure all intrinsic calls are eliminated when the input is known 58; positive. 59 60; The fabs cannot be eliminated because %x may be a NaN 61 62define float @square_fabs_intrinsic_f32(float %x) { 63; CHECK-LABEL: @square_fabs_intrinsic_f32( 64; CHECK-NEXT: [[MUL:%.*]] = fmul float [[X:%.*]], [[X]] 65; CHECK-NEXT: [[FABSF:%.*]] = tail call float @llvm.fabs.f32(float [[MUL]]) 66; CHECK-NEXT: ret float [[FABSF]] 67; 68 %mul = fmul float %x, %x 69 %fabsf = tail call float @llvm.fabs.f32(float %mul) 70 ret float %fabsf 71} 72 73define double @square_fabs_intrinsic_f64(double %x) { 74; CHECK-LABEL: @square_fabs_intrinsic_f64( 75; CHECK-NEXT: [[MUL:%.*]] = fmul double [[X:%.*]], [[X]] 76; CHECK-NEXT: [[FABS:%.*]] = tail call double @llvm.fabs.f64(double [[MUL]]) 77; CHECK-NEXT: ret double [[FABS]] 78; 79 %mul = fmul double %x, %x 80 %fabs = tail call double @llvm.fabs.f64(double %mul) 81 ret double %fabs 82} 83 84define fp128 @square_fabs_intrinsic_f128(fp128 %x) { 85; CHECK-LABEL: @square_fabs_intrinsic_f128( 86; CHECK-NEXT: [[MUL:%.*]] = fmul fp128 [[X:%.*]], [[X]] 87; CHECK-NEXT: [[FABSL:%.*]] = tail call fp128 @llvm.fabs.f128(fp128 [[MUL]]) 88; CHECK-NEXT: ret fp128 [[FABSL]] 89; 90 %mul = fmul fp128 %x, %x 91 %fabsl = tail call fp128 @llvm.fabs.f128(fp128 %mul) 92 ret fp128 %fabsl 93} 94 95define float @square_nnan_fabs_intrinsic_f32(float %x) { 96; CHECK-LABEL: @square_nnan_fabs_intrinsic_f32( 97; CHECK-NEXT: [[MUL:%.*]] = fmul nnan float [[X:%.*]], [[X]] 98; CHECK-NEXT: ret float [[MUL]] 99; 100 %mul = fmul nnan float %x, %x 101 %fabsf = call float @llvm.fabs.f32(float %mul) 102 ret float %fabsf 103} 104 105; Shrinking a library call to a smaller type should not be inhibited by nor inhibit the square optimization. 106 107define float @square_fabs_shrink_call1(float %x) { 108; CHECK-LABEL: @square_fabs_shrink_call1( 109; CHECK-NEXT: [[TMP1:%.*]] = fmul float [[X:%.*]], [[X]] 110; CHECK-NEXT: [[TRUNC:%.*]] = call float @llvm.fabs.f32(float [[TMP1]]) 111; CHECK-NEXT: ret float [[TRUNC]] 112; 113 %ext = fpext float %x to double 114 %sq = fmul double %ext, %ext 115 %fabs = call double @fabs(double %sq) 116 %trunc = fptrunc double %fabs to float 117 ret float %trunc 118} 119 120define float @square_fabs_shrink_call2(float %x) { 121; CHECK-LABEL: @square_fabs_shrink_call2( 122; CHECK-NEXT: [[SQ:%.*]] = fmul float [[X:%.*]], [[X]] 123; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[SQ]]) 124; CHECK-NEXT: ret float [[TMP1]] 125; 126 %sq = fmul float %x, %x 127 %ext = fpext float %sq to double 128 %fabs = call double @fabs(double %ext) 129 %trunc = fptrunc double %fabs to float 130 ret float %trunc 131} 132 133define float @fabs_select_constant_negative_positive(i32 %c) { 134; CHECK-LABEL: @fabs_select_constant_negative_positive( 135; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 136; CHECK-NEXT: [[FABS:%.*]] = select i1 [[CMP]], float 1.000000e+00, float 2.000000e+00 137; CHECK-NEXT: ret float [[FABS]] 138; 139 %cmp = icmp eq i32 %c, 0 140 %select = select i1 %cmp, float -1.0, float 2.0 141 %fabs = call float @llvm.fabs.f32(float %select) 142 ret float %fabs 143} 144 145define float @fabs_select_constant_positive_negative(i32 %c) { 146; CHECK-LABEL: @fabs_select_constant_positive_negative( 147; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 148; CHECK-NEXT: [[FABS:%.*]] = select i1 [[CMP]], float 1.000000e+00, float 2.000000e+00 149; CHECK-NEXT: ret float [[FABS]] 150; 151 %cmp = icmp eq i32 %c, 0 152 %select = select i1 %cmp, float 1.0, float -2.0 153 %fabs = call float @llvm.fabs.f32(float %select) 154 ret float %fabs 155} 156 157define float @fabs_select_constant_negative_negative(i32 %c) { 158; CHECK-LABEL: @fabs_select_constant_negative_negative( 159; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 160; CHECK-NEXT: [[FABS:%.*]] = select i1 [[CMP]], float 1.000000e+00, float 2.000000e+00 161; CHECK-NEXT: ret float [[FABS]] 162; 163 %cmp = icmp eq i32 %c, 0 164 %select = select i1 %cmp, float -1.0, float -2.0 165 %fabs = call float @llvm.fabs.f32(float %select) 166 ret float %fabs 167} 168 169define float @fabs_select_constant_neg0(i32 %c) { 170; CHECK-LABEL: @fabs_select_constant_neg0( 171; CHECK-NEXT: ret float 0.000000e+00 172; 173 %cmp = icmp eq i32 %c, 0 174 %select = select i1 %cmp, float -0.0, float 0.0 175 %fabs = call float @llvm.fabs.f32(float %select) 176 ret float %fabs 177} 178 179define float @fabs_select_var_constant_negative(i32 %c, float %x) { 180; CHECK-LABEL: @fabs_select_var_constant_negative( 181; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 182; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT:%.*]]) 183; CHECK-NEXT: [[FABS1:%.*]] = select i1 [[CMP]], float [[FABS]], float 1.000000e+00 184; CHECK-NEXT: ret float [[FABS1]] 185; 186 %cmp = icmp eq i32 %c, 0 187 %select = select i1 %cmp, float %x, float -1.0 188 %fabs = call float @llvm.fabs.f32(float %select) 189 ret float %fabs 190} 191 192; The fabs cannot be eliminated because %x may be a NaN 193 194define float @square_fma_fabs_intrinsic_f32(float %x) { 195; CHECK-LABEL: @square_fma_fabs_intrinsic_f32( 196; CHECK-NEXT: [[FMA:%.*]] = call float @llvm.fma.f32(float [[X:%.*]], float [[X]], float 1.000000e+00) 197; CHECK-NEXT: [[FABSF:%.*]] = call float @llvm.fabs.f32(float [[FMA]]) 198; CHECK-NEXT: ret float [[FABSF]] 199; 200 %fma = call float @llvm.fma.f32(float %x, float %x, float 1.0) 201 %fabsf = call float @llvm.fabs.f32(float %fma) 202 ret float %fabsf 203} 204 205; The fabs cannot be eliminated because %x may be a NaN 206 207define float @square_nnan_fma_fabs_intrinsic_f32(float %x) { 208; CHECK-LABEL: @square_nnan_fma_fabs_intrinsic_f32( 209; CHECK-NEXT: [[FMA:%.*]] = call nnan float @llvm.fma.f32(float [[X:%.*]], float [[X]], float 1.000000e+00) 210; CHECK-NEXT: ret float [[FMA]] 211; 212 %fma = call nnan float @llvm.fma.f32(float %x, float %x, float 1.0) 213 %fabsf = call float @llvm.fabs.f32(float %fma) 214 ret float %fabsf 215} 216 217define float @square_fmuladd_fabs_intrinsic_f32(float %x) { 218; CHECK-LABEL: @square_fmuladd_fabs_intrinsic_f32( 219; CHECK-NEXT: [[FMULADD:%.*]] = call float @llvm.fmuladd.f32(float [[X:%.*]], float [[X]], float 1.000000e+00) 220; CHECK-NEXT: [[FABSF:%.*]] = call float @llvm.fabs.f32(float [[FMULADD]]) 221; CHECK-NEXT: ret float [[FABSF]] 222; 223 %fmuladd = call float @llvm.fmuladd.f32(float %x, float %x, float 1.0) 224 %fabsf = call float @llvm.fabs.f32(float %fmuladd) 225 ret float %fabsf 226} 227 228define float @square_nnan_fmuladd_fabs_intrinsic_f32(float %x) { 229; CHECK-LABEL: @square_nnan_fmuladd_fabs_intrinsic_f32( 230; CHECK-NEXT: [[FMULADD:%.*]] = call nnan float @llvm.fmuladd.f32(float [[X:%.*]], float [[X]], float 1.000000e+00) 231; CHECK-NEXT: ret float [[FMULADD]] 232; 233 %fmuladd = call nnan float @llvm.fmuladd.f32(float %x, float %x, float 1.0) 234 %fabsf = call float @llvm.fabs.f32(float %fmuladd) 235 ret float %fabsf 236} 237 238; Don't introduce a second fpext 239 240define double @multi_use_fabs_fpext(float %x) { 241; CHECK-LABEL: @multi_use_fabs_fpext( 242; CHECK-NEXT: [[FPEXT:%.*]] = fpext float [[X:%.*]] to double 243; CHECK-NEXT: [[FABS:%.*]] = call double @llvm.fabs.f64(double [[FPEXT]]) 244; CHECK-NEXT: store volatile double [[FPEXT]], ptr undef, align 8 245; CHECK-NEXT: ret double [[FABS]] 246; 247 %fpext = fpext float %x to double 248 %fabs = call double @llvm.fabs.f64(double %fpext) 249 store volatile double %fpext, ptr undef 250 ret double %fabs 251} 252 253; X <= 0.0 ? (0.0 - X) : X --> fabs(X) 254 255define double @select_fcmp_ole_zero(double %x) { 256; CHECK-LABEL: @select_fcmp_ole_zero( 257; CHECK-NEXT: [[FABS:%.*]] = call double @llvm.fabs.f64(double [[X:%.*]]) 258; CHECK-NEXT: ret double [[FABS]] 259; 260 %lezero = fcmp ole double %x, 0.0 261 %negx = fsub double 0.0, %x 262 %fabs = select i1 %lezero, double %negx, double %x 263 ret double %fabs 264} 265 266define double @select_fcmp_nnan_ole_zero(double %x) { 267; CHECK-LABEL: @select_fcmp_nnan_ole_zero( 268; CHECK-NEXT: [[FABS:%.*]] = call double @llvm.fabs.f64(double [[X:%.*]]) 269; CHECK-NEXT: ret double [[FABS]] 270; 271 %lezero = fcmp ole double %x, 0.0 272 %negx = fsub nnan double 0.0, %x 273 %fabs = select i1 %lezero, double %negx, double %x 274 ret double %fabs 275} 276 277define double @select_nnan_fcmp_nnan_ole_zero(double %x) { 278; CHECK-LABEL: @select_nnan_fcmp_nnan_ole_zero( 279; CHECK-NEXT: [[FABS:%.*]] = call nnan double @llvm.fabs.f64(double [[X:%.*]]) 280; CHECK-NEXT: ret double [[FABS]] 281; 282 %lezero = fcmp ole double %x, 0.0 283 %negx = fsub nnan double 0.0, %x 284 %fabs = select nnan i1 %lezero, double %negx, double %x 285 ret double %fabs 286} 287 288; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically. 289 290define double @select_fcmp_nnan_ule_zero(double %x) { 291; CHECK-LABEL: @select_fcmp_nnan_ule_zero( 292; CHECK-NEXT: [[FABS:%.*]] = call double @llvm.fabs.f64(double [[X:%.*]]) 293; CHECK-NEXT: ret double [[FABS]] 294; 295 %lezero = fcmp ule double %x, 0.0 296 %negx = fsub nnan double 0.0, %x 297 %fabs = select i1 %lezero, double %negx, double %x 298 ret double %fabs 299} 300 301; Negative test - wrong predicate. 302 303define double @select_fcmp_nnan_olt_zero(double %x) { 304; CHECK-LABEL: @select_fcmp_nnan_olt_zero( 305; CHECK-NEXT: [[LEZERO:%.*]] = fcmp olt double [[X:%.*]], 0.000000e+00 306; CHECK-NEXT: [[NEGX:%.*]] = fsub nnan double 0.000000e+00, [[X]] 307; CHECK-NEXT: [[FABS:%.*]] = select i1 [[LEZERO]], double [[NEGX]], double [[X]] 308; CHECK-NEXT: ret double [[FABS]] 309; 310 %lezero = fcmp olt double %x, 0.0 311 %negx = fsub nnan double 0.0, %x 312 %fabs = select i1 %lezero, double %negx, double %x 313 ret double %fabs 314} 315 316; X <= -0.0 ? (0.0 - X) : X --> fabs(X) 317 318define <2 x float> @select_fcmp_nnan_ole_negzero(<2 x float> %x) { 319; CHECK-LABEL: @select_fcmp_nnan_ole_negzero( 320; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[X:%.*]]) 321; CHECK-NEXT: ret <2 x float> [[FABS]] 322; 323 %lezero = fcmp ole <2 x float> %x, <float -0.0, float -0.0> 324 %negx = fsub nnan <2 x float> <float 0.0, float poison>, %x 325 %fabs = select <2 x i1> %lezero, <2 x float> %negx, <2 x float> %x 326 ret <2 x float> %fabs 327} 328 329define <2 x float> @select_nnan_fcmp_nnan_ole_negzero(<2 x float> %x) { 330; CHECK-LABEL: @select_nnan_fcmp_nnan_ole_negzero( 331; CHECK-NEXT: [[FABS:%.*]] = call nnan <2 x float> @llvm.fabs.v2f32(<2 x float> [[X:%.*]]) 332; CHECK-NEXT: ret <2 x float> [[FABS]] 333; 334 %lezero = fcmp ole <2 x float> %x, <float -0.0, float -0.0> 335 %negx = fsub nnan <2 x float> <float 0.0, float poison>, %x 336 %fabs = select nnan <2 x i1> %lezero, <2 x float> %negx, <2 x float> %x 337 ret <2 x float> %fabs 338} 339 340; X > 0.0 ? X : (0.0 - X) --> fabs(X) 341 342define fp128 @select_fcmp_ogt_zero(fp128 %x) { 343; CHECK-LABEL: @select_fcmp_ogt_zero( 344; CHECK-NEXT: [[FABS:%.*]] = call fp128 @llvm.fabs.f128(fp128 [[X:%.*]]) 345; CHECK-NEXT: ret fp128 [[FABS]] 346; 347 %gtzero = fcmp ogt fp128 %x, zeroinitializer 348 %negx = fsub fp128 zeroinitializer, %x 349 %fabs = select i1 %gtzero, fp128 %x, fp128 %negx 350 ret fp128 %fabs 351} 352 353; This is not fabs because that could produce a different signbit for a NAN input. 354; PR59279 355 356define float @select_nsz_fcmp_ogt_fneg(float %a) { 357; CHECK-LABEL: @select_nsz_fcmp_ogt_fneg( 358; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[A:%.*]] 359; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[A]], 0.000000e+00 360; CHECK-NEXT: [[R:%.*]] = select nsz i1 [[CMP]], float [[A]], float [[FNEG]] 361; CHECK-NEXT: ret float [[R]] 362; 363 %fneg = fneg float %a 364 %cmp = fcmp ogt float %a, %fneg 365 %r = select nsz i1 %cmp, float %a, float %fneg 366 ret float %r 367} 368 369define float @select_nsz_nnan_fcmp_ogt_fneg(float %a) { 370; CHECK-LABEL: @select_nsz_nnan_fcmp_ogt_fneg( 371; CHECK-NEXT: [[R:%.*]] = call nnan nsz float @llvm.fabs.f32(float [[A:%.*]]) 372; CHECK-NEXT: ret float [[R]] 373; 374 %fneg = fneg float %a 375 %cmp = fcmp ogt float %a, %fneg 376 %r = select nsz nnan i1 %cmp, float %a, float %fneg 377 ret float %r 378} 379 380define fp128 @select_fcmp_nnan_ogt_zero(fp128 %x) { 381; CHECK-LABEL: @select_fcmp_nnan_ogt_zero( 382; CHECK-NEXT: [[FABS:%.*]] = call fp128 @llvm.fabs.f128(fp128 [[X:%.*]]) 383; CHECK-NEXT: ret fp128 [[FABS]] 384; 385 %gtzero = fcmp ogt fp128 %x, zeroinitializer 386 %negx = fsub nnan fp128 zeroinitializer, %x 387 %fabs = select i1 %gtzero, fp128 %x, fp128 %negx 388 ret fp128 %fabs 389} 390 391define fp128 @select_nnan_fcmp_nnan_ogt_zero(fp128 %x) { 392; CHECK-LABEL: @select_nnan_fcmp_nnan_ogt_zero( 393; CHECK-NEXT: [[FABS:%.*]] = call nnan fp128 @llvm.fabs.f128(fp128 [[X:%.*]]) 394; CHECK-NEXT: ret fp128 [[FABS]] 395; 396 %gtzero = fcmp ogt fp128 %x, zeroinitializer 397 %negx = fsub nnan fp128 zeroinitializer, %x 398 %fabs = select nnan i1 %gtzero, fp128 %x, fp128 %negx 399 ret fp128 %fabs 400} 401 402; X > -0.0 ? X : (0.0 - X) --> fabs(X) 403 404define half @select_fcmp_nnan_ogt_negzero(half %x) { 405; CHECK-LABEL: @select_fcmp_nnan_ogt_negzero( 406; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) 407; CHECK-NEXT: ret half [[FABS]] 408; 409 %gtzero = fcmp ogt half %x, -0.0 410 %negx = fsub nnan half 0.0, %x 411 %fabs = select i1 %gtzero, half %x, half %negx 412 ret half %fabs 413} 414 415define half @select_nnan_fcmp_nnan_ogt_negzero(half %x) { 416; CHECK-LABEL: @select_nnan_fcmp_nnan_ogt_negzero( 417; CHECK-NEXT: [[FABS:%.*]] = call nnan half @llvm.fabs.f16(half [[X:%.*]]) 418; CHECK-NEXT: ret half [[FABS]] 419; 420 %gtzero = fcmp ogt half %x, -0.0 421 %negx = fsub nnan half 0.0, %x 422 %fabs = select nnan i1 %gtzero, half %x, half %negx 423 ret half %fabs 424} 425 426; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically. 427 428define half @select_fcmp_nnan_ugt_negzero(half %x) { 429; CHECK-LABEL: @select_fcmp_nnan_ugt_negzero( 430; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) 431; CHECK-NEXT: ret half [[FABS]] 432; 433 %gtzero = fcmp ugt half %x, -0.0 434 %negx = fsub nnan half 0.0, %x 435 %fabs = select i1 %gtzero, half %x, half %negx 436 ret half %fabs 437} 438 439; Negative test - wrong predicate. 440 441define half @select_fcmp_nnan_oge_negzero(half %x) { 442; CHECK-LABEL: @select_fcmp_nnan_oge_negzero( 443; CHECK-NEXT: [[GTZERO:%.*]] = fcmp oge half [[X:%.*]], 0xH0000 444; CHECK-NEXT: [[NEGX:%.*]] = fsub nnan half 0xH0000, [[X]] 445; CHECK-NEXT: [[FABS:%.*]] = select i1 [[GTZERO]], half [[X]], half [[NEGX]] 446; CHECK-NEXT: ret half [[FABS]] 447; 448 %gtzero = fcmp oge half %x, -0.0 449 %negx = fsub nnan half 0.0, %x 450 %fabs = select i1 %gtzero, half %x, half %negx 451 ret half %fabs 452} 453 454; This is not fabs because that could produce a different signbit for a NAN input. 455; PR59279 456 457define double @select_nsz_fcmp_olt_zero_unary_fneg(double %x) { 458; CHECK-LABEL: @select_nsz_fcmp_olt_zero_unary_fneg( 459; CHECK-NEXT: [[LTZERO:%.*]] = fcmp olt double [[X:%.*]], 0.000000e+00 460; CHECK-NEXT: [[NEGX:%.*]] = fneg double [[X]] 461; CHECK-NEXT: [[FABS:%.*]] = select nsz i1 [[LTZERO]], double [[NEGX]], double [[X]] 462; CHECK-NEXT: ret double [[FABS]] 463; 464 %ltzero = fcmp olt double %x, 0.0 465 %negx = fneg double %x 466 %fabs = select nsz i1 %ltzero, double %negx, double %x 467 ret double %fabs 468} 469 470; X < 0.0 ? -X : X --> fabs(X) 471 472define double @select_nsz_nnan_fcmp_olt_zero_unary_fneg(double %x) { 473; CHECK-LABEL: @select_nsz_nnan_fcmp_olt_zero_unary_fneg( 474; CHECK-NEXT: [[FABS:%.*]] = call nnan nsz double @llvm.fabs.f64(double [[X:%.*]]) 475; CHECK-NEXT: ret double [[FABS]] 476; 477 %ltzero = fcmp olt double %x, 0.0 478 %negx = fneg double %x 479 %fabs = select nsz nnan i1 %ltzero, double %negx, double %x 480 ret double %fabs 481} 482 483define double @select_fcmp_nnan_nsz_olt_zero(double %x) { 484; CHECK-LABEL: @select_fcmp_nnan_nsz_olt_zero( 485; CHECK-NEXT: [[LTZERO:%.*]] = fcmp olt double [[X:%.*]], 0.000000e+00 486; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan nsz double [[X]] 487; CHECK-NEXT: [[FABS:%.*]] = select nnan i1 [[LTZERO]], double [[NEGX]], double [[X]] 488; CHECK-NEXT: ret double [[FABS]] 489; 490 %ltzero = fcmp olt double %x, 0.0 491 %negx = fsub nnan nsz double -0.0, %x 492 %fabs = select i1 %ltzero, double %negx, double %x 493 ret double %fabs 494} 495 496define double @select_nnan_nsz_fcmp_nnan_nsz_olt_zero(double %x) { 497; CHECK-LABEL: @select_nnan_nsz_fcmp_nnan_nsz_olt_zero( 498; CHECK-NEXT: [[FABS:%.*]] = call nnan nsz double @llvm.fabs.f64(double [[X:%.*]]) 499; CHECK-NEXT: ret double [[FABS]] 500; 501 %ltzero = fcmp olt double %x, 0.0 502 %negx = fsub nnan nsz double -0.0, %x 503 %fabs = select nnan nsz i1 %ltzero, double %negx, double %x 504 ret double %fabs 505} 506 507; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically. 508 509define double @select_fcmp_nnan_nsz_ult_zero(double %x) { 510; CHECK-LABEL: @select_fcmp_nnan_nsz_ult_zero( 511; CHECK-NEXT: [[LTZERO:%.*]] = fcmp ult double [[X:%.*]], 0.000000e+00 512; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan nsz double [[X]] 513; CHECK-NEXT: [[FABS:%.*]] = select nnan i1 [[LTZERO]], double [[NEGX]], double [[X]] 514; CHECK-NEXT: ret double [[FABS]] 515; 516 %ltzero = fcmp ult double %x, 0.0 517 %negx = fsub nnan nsz double -0.0, %x 518 %fabs = select i1 %ltzero, double %negx, double %x 519 ret double %fabs 520} 521 522define double @select_fcmp_nnan_nsz_olt_zero_unary_fneg(double %x) { 523; CHECK-LABEL: @select_fcmp_nnan_nsz_olt_zero_unary_fneg( 524; CHECK-NEXT: [[LTZERO:%.*]] = fcmp olt double [[X:%.*]], 0.000000e+00 525; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan nsz double [[X]] 526; CHECK-NEXT: [[FABS:%.*]] = select nnan i1 [[LTZERO]], double [[NEGX]], double [[X]] 527; CHECK-NEXT: ret double [[FABS]] 528; 529 %ltzero = fcmp olt double %x, 0.0 530 %negx = fneg nnan nsz double %x 531 %fabs = select i1 %ltzero, double %negx, double %x 532 ret double %fabs 533} 534 535; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically. 536 537define double @select_fcmp_nnan_nsz_ult_zero_unary_fneg(double %x) { 538; CHECK-LABEL: @select_fcmp_nnan_nsz_ult_zero_unary_fneg( 539; CHECK-NEXT: [[LTZERO:%.*]] = fcmp ult double [[X:%.*]], 0.000000e+00 540; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan nsz double [[X]] 541; CHECK-NEXT: [[FABS:%.*]] = select nnan i1 [[LTZERO]], double [[NEGX]], double [[X]] 542; CHECK-NEXT: ret double [[FABS]] 543; 544 %ltzero = fcmp ult double %x, 0.0 545 %negx = fneg nnan nsz double %x 546 %fabs = select i1 %ltzero, double %negx, double %x 547 ret double %fabs 548} 549 550; X < -0.0 ? -X : X --> fabs(X) 551 552define float @select_fcmp_nnan_nsz_olt_negzero(float %x) { 553; CHECK-LABEL: @select_fcmp_nnan_nsz_olt_negzero( 554; CHECK-NEXT: [[LTZERO:%.*]] = fcmp olt float [[X:%.*]], 0.000000e+00 555; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan ninf nsz float [[X]] 556; CHECK-NEXT: [[FABS:%.*]] = select nnan ninf i1 [[LTZERO]], float [[NEGX]], float [[X]] 557; CHECK-NEXT: ret float [[FABS]] 558; 559 %ltzero = fcmp olt float %x, -0.0 560 %negx = fsub nnan ninf nsz float -0.0, %x 561 %fabs = select i1 %ltzero, float %negx, float %x 562 ret float %fabs 563} 564 565define float @select_nnan_ninf_nsz_fcmp_nnan_nsz_olt_negzero(float %x) { 566; CHECK-LABEL: @select_nnan_ninf_nsz_fcmp_nnan_nsz_olt_negzero( 567; CHECK-NEXT: [[FABS:%.*]] = call nnan ninf nsz float @llvm.fabs.f32(float [[X:%.*]]) 568; CHECK-NEXT: ret float [[FABS]] 569; 570 %ltzero = fcmp olt float %x, -0.0 571 %negx = fsub nnan nsz float -0.0, %x 572 %fabs = select nnan ninf nsz i1 %ltzero, float %negx, float %x 573 ret float %fabs 574} 575 576; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically. 577 578define float @select_fcmp_nnan_nsz_ult_negzero(float %x) { 579; CHECK-LABEL: @select_fcmp_nnan_nsz_ult_negzero( 580; CHECK-NEXT: [[LTZERO:%.*]] = fcmp ult float [[X:%.*]], 0.000000e+00 581; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan ninf nsz float [[X]] 582; CHECK-NEXT: [[FABS:%.*]] = select nnan ninf i1 [[LTZERO]], float [[NEGX]], float [[X]] 583; CHECK-NEXT: ret float [[FABS]] 584; 585 %ltzero = fcmp ult float %x, -0.0 586 %negx = fsub nnan ninf nsz float -0.0, %x 587 %fabs = select i1 %ltzero, float %negx, float %x 588 ret float %fabs 589} 590 591define float @select_fcmp_nnan_nsz_olt_negzero_unary_fneg(float %x) { 592; CHECK-LABEL: @select_fcmp_nnan_nsz_olt_negzero_unary_fneg( 593; CHECK-NEXT: [[LTZERO:%.*]] = fcmp olt float [[X:%.*]], 0.000000e+00 594; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan ninf nsz float [[X]] 595; CHECK-NEXT: [[FABS:%.*]] = select nnan ninf i1 [[LTZERO]], float [[NEGX]], float [[X]] 596; CHECK-NEXT: ret float [[FABS]] 597; 598 %ltzero = fcmp olt float %x, -0.0 599 %negx = fneg nnan ninf nsz float %x 600 %fabs = select i1 %ltzero, float %negx, float %x 601 ret float %fabs 602} 603 604; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically. 605 606define float @select_fcmp_nnan_nsz_ult_negzero_unary_fneg(float %x) { 607; CHECK-LABEL: @select_fcmp_nnan_nsz_ult_negzero_unary_fneg( 608; CHECK-NEXT: [[LTZERO:%.*]] = fcmp ult float [[X:%.*]], 0.000000e+00 609; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan ninf nsz float [[X]] 610; CHECK-NEXT: [[FABS:%.*]] = select nnan ninf i1 [[LTZERO]], float [[NEGX]], float [[X]] 611; CHECK-NEXT: ret float [[FABS]] 612; 613 %ltzero = fcmp ult float %x, -0.0 614 %negx = fneg nnan ninf nsz float %x 615 %fabs = select i1 %ltzero, float %negx, float %x 616 ret float %fabs 617} 618 619; X <= 0.0 ? -X : X --> fabs(X) 620 621define double @select_fcmp_nnan_nsz_ole_zero(double %x) { 622; CHECK-LABEL: @select_fcmp_nnan_nsz_ole_zero( 623; CHECK-NEXT: [[LEZERO:%.*]] = fcmp ole double [[X:%.*]], 0.000000e+00 624; CHECK-NEXT: [[NEGX:%.*]] = fneg fast double [[X]] 625; CHECK-NEXT: [[FABS:%.*]] = select nnan ninf i1 [[LEZERO]], double [[NEGX]], double [[X]] 626; CHECK-NEXT: ret double [[FABS]] 627; 628 %lezero = fcmp ole double %x, 0.0 629 %negx = fsub fast double -0.0, %x 630 %fabs = select i1 %lezero, double %negx, double %x 631 ret double %fabs 632} 633 634define double @select_fast_fcmp_nnan_nsz_ole_zero(double %x) { 635; CHECK-LABEL: @select_fast_fcmp_nnan_nsz_ole_zero( 636; CHECK-NEXT: [[FABS:%.*]] = call fast double @llvm.fabs.f64(double [[X:%.*]]) 637; CHECK-NEXT: ret double [[FABS]] 638; 639 %lezero = fcmp ole double %x, 0.0 640 %negx = fsub nnan nsz double -0.0, %x 641 %fabs = select fast i1 %lezero, double %negx, double %x 642 ret double %fabs 643} 644 645; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically. 646 647define double @select_fcmp_nnan_nsz_ule_zero(double %x) { 648; CHECK-LABEL: @select_fcmp_nnan_nsz_ule_zero( 649; CHECK-NEXT: [[LEZERO:%.*]] = fcmp ule double [[X:%.*]], 0.000000e+00 650; CHECK-NEXT: [[NEGX:%.*]] = fneg fast double [[X]] 651; CHECK-NEXT: [[FABS:%.*]] = select nnan ninf i1 [[LEZERO]], double [[NEGX]], double [[X]] 652; CHECK-NEXT: ret double [[FABS]] 653; 654 %lezero = fcmp ule double %x, 0.0 655 %negx = fsub fast double -0.0, %x 656 %fabs = select i1 %lezero, double %negx, double %x 657 ret double %fabs 658} 659 660define double @select_fcmp_nnan_nsz_ole_zero_unary_fneg(double %x) { 661; CHECK-LABEL: @select_fcmp_nnan_nsz_ole_zero_unary_fneg( 662; CHECK-NEXT: [[LEZERO:%.*]] = fcmp ole double [[X:%.*]], 0.000000e+00 663; CHECK-NEXT: [[NEGX:%.*]] = fneg fast double [[X]] 664; CHECK-NEXT: [[FABS:%.*]] = select nnan ninf i1 [[LEZERO]], double [[NEGX]], double [[X]] 665; CHECK-NEXT: ret double [[FABS]] 666; 667 %lezero = fcmp ole double %x, 0.0 668 %negx = fneg fast double %x 669 %fabs = select i1 %lezero, double %negx, double %x 670 ret double %fabs 671} 672 673; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically. 674 675define double @select_fcmp_nnan_nsz_ule_zero_unary_fneg(double %x) { 676; CHECK-LABEL: @select_fcmp_nnan_nsz_ule_zero_unary_fneg( 677; CHECK-NEXT: [[LEZERO:%.*]] = fcmp ule double [[X:%.*]], 0.000000e+00 678; CHECK-NEXT: [[NEGX:%.*]] = fneg fast double [[X]] 679; CHECK-NEXT: [[FABS:%.*]] = select nnan ninf i1 [[LEZERO]], double [[NEGX]], double [[X]] 680; CHECK-NEXT: ret double [[FABS]] 681; 682 %lezero = fcmp ule double %x, 0.0 683 %negx = fneg fast double %x 684 %fabs = select i1 %lezero, double %negx, double %x 685 ret double %fabs 686} 687 688; X <= -0.0 ? -X : X --> fabs(X) 689 690define float @select_fcmp_nnan_nsz_ole_negzero(float %x) { 691; CHECK-LABEL: @select_fcmp_nnan_nsz_ole_negzero( 692; CHECK-NEXT: [[LEZERO:%.*]] = fcmp ole float [[X:%.*]], 0.000000e+00 693; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan nsz float [[X]] 694; CHECK-NEXT: [[FABS:%.*]] = select nnan i1 [[LEZERO]], float [[NEGX]], float [[X]] 695; CHECK-NEXT: ret float [[FABS]] 696; 697 %lezero = fcmp ole float %x, -0.0 698 %negx = fsub nnan nsz float -0.0, %x 699 %fabs = select i1 %lezero, float %negx, float %x 700 ret float %fabs 701} 702 703define float @select_nnan_nsz_fcmp_nnan_nsz_ole_negzero(float %x) { 704; CHECK-LABEL: @select_nnan_nsz_fcmp_nnan_nsz_ole_negzero( 705; CHECK-NEXT: [[FABS:%.*]] = call nnan nsz float @llvm.fabs.f32(float [[X:%.*]]) 706; CHECK-NEXT: ret float [[FABS]] 707; 708 %lezero = fcmp ole float %x, -0.0 709 %negx = fsub nnan nsz float -0.0, %x 710 %fabs = select nnan nsz i1 %lezero, float %negx, float %x 711 ret float %fabs 712} 713 714; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically. 715 716define float @select_fcmp_nnan_nsz_ule_negzero(float %x) { 717; CHECK-LABEL: @select_fcmp_nnan_nsz_ule_negzero( 718; CHECK-NEXT: [[LEZERO:%.*]] = fcmp ule float [[X:%.*]], 0.000000e+00 719; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan nsz float [[X]] 720; CHECK-NEXT: [[FABS:%.*]] = select nnan i1 [[LEZERO]], float [[NEGX]], float [[X]] 721; CHECK-NEXT: ret float [[FABS]] 722; 723 %lezero = fcmp ule float %x, -0.0 724 %negx = fsub nnan nsz float -0.0, %x 725 %fabs = select i1 %lezero, float %negx, float %x 726 ret float %fabs 727} 728 729define float @select_fcmp_nnan_nsz_ole_negzero_unary_fneg(float %x) { 730; CHECK-LABEL: @select_fcmp_nnan_nsz_ole_negzero_unary_fneg( 731; CHECK-NEXT: [[LEZERO:%.*]] = fcmp ole float [[X:%.*]], 0.000000e+00 732; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan nsz float [[X]] 733; CHECK-NEXT: [[FABS:%.*]] = select nnan i1 [[LEZERO]], float [[NEGX]], float [[X]] 734; CHECK-NEXT: ret float [[FABS]] 735; 736 %lezero = fcmp ole float %x, -0.0 737 %negx = fneg nnan nsz float %x 738 %fabs = select i1 %lezero, float %negx, float %x 739 ret float %fabs 740} 741 742; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically. 743 744define float @select_fcmp_nnan_nsz_ule_negzero_unary_fneg(float %x) { 745; CHECK-LABEL: @select_fcmp_nnan_nsz_ule_negzero_unary_fneg( 746; CHECK-NEXT: [[LEZERO:%.*]] = fcmp ule float [[X:%.*]], 0.000000e+00 747; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan nsz float [[X]] 748; CHECK-NEXT: [[FABS:%.*]] = select nnan i1 [[LEZERO]], float [[NEGX]], float [[X]] 749; CHECK-NEXT: ret float [[FABS]] 750; 751 %lezero = fcmp ule float %x, -0.0 752 %negx = fneg nnan nsz float %x 753 %fabs = select i1 %lezero, float %negx, float %x 754 ret float %fabs 755} 756 757; This is not fabs because that could produce a different signbit for a NAN input. 758; PR59279 759 760define <2 x float> @select_nsz_fcmp_ogt_zero_unary_fneg(<2 x float> %x) { 761; CHECK-LABEL: @select_nsz_fcmp_ogt_zero_unary_fneg( 762; CHECK-NEXT: [[GTZERO:%.*]] = fcmp ogt <2 x float> [[X:%.*]], zeroinitializer 763; CHECK-NEXT: [[NEGX:%.*]] = fneg <2 x float> [[X]] 764; CHECK-NEXT: [[FABS:%.*]] = select nsz <2 x i1> [[GTZERO]], <2 x float> [[X]], <2 x float> [[NEGX]] 765; CHECK-NEXT: ret <2 x float> [[FABS]] 766; 767 %gtzero = fcmp ogt <2 x float> %x, zeroinitializer 768 %negx = fneg <2 x float> %x 769 %fabs = select nsz <2 x i1> %gtzero, <2 x float> %x, <2 x float> %negx 770 ret <2 x float> %fabs 771} 772 773; X > 0.0 ? X : (-X) --> fabs(X) 774 775define <2 x float> @select_nsz_nnan_fcmp_ogt_zero_unary_fneg(<2 x float> %x) { 776; CHECK-LABEL: @select_nsz_nnan_fcmp_ogt_zero_unary_fneg( 777; CHECK-NEXT: [[FABS:%.*]] = call nnan nsz <2 x float> @llvm.fabs.v2f32(<2 x float> [[X:%.*]]) 778; CHECK-NEXT: ret <2 x float> [[FABS]] 779; 780 %gtzero = fcmp ogt <2 x float> %x, zeroinitializer 781 %negx = fneg <2 x float> %x 782 %fabs = select nsz nnan <2 x i1> %gtzero, <2 x float> %x, <2 x float> %negx 783 ret <2 x float> %fabs 784} 785 786define <2 x float> @select_fcmp_nnan_nsz_ogt_zero(<2 x float> %x) { 787; CHECK-LABEL: @select_fcmp_nnan_nsz_ogt_zero( 788; CHECK-NEXT: [[GTZERO:%.*]] = fcmp ogt <2 x float> [[X:%.*]], zeroinitializer 789; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan nsz arcp <2 x float> [[X]] 790; CHECK-NEXT: [[FABS:%.*]] = select nnan <2 x i1> [[GTZERO]], <2 x float> [[X]], <2 x float> [[NEGX]] 791; CHECK-NEXT: ret <2 x float> [[FABS]] 792; 793 %gtzero = fcmp ogt <2 x float> %x, zeroinitializer 794 %negx = fsub nnan nsz arcp <2 x float> <float -0.0, float -0.0>, %x 795 %fabs = select <2 x i1> %gtzero, <2 x float> %x, <2 x float> %negx 796 ret <2 x float> %fabs 797} 798 799; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically. 800 801define <2 x float> @select_fcmp_nnan_nsz_ugt_zero(<2 x float> %x) { 802; CHECK-LABEL: @select_fcmp_nnan_nsz_ugt_zero( 803; CHECK-NEXT: [[GTZERO:%.*]] = fcmp ugt <2 x float> [[X:%.*]], zeroinitializer 804; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan nsz arcp <2 x float> [[X]] 805; CHECK-NEXT: [[FABS:%.*]] = select nnan <2 x i1> [[GTZERO]], <2 x float> [[X]], <2 x float> [[NEGX]] 806; CHECK-NEXT: ret <2 x float> [[FABS]] 807; 808 %gtzero = fcmp ugt <2 x float> %x, zeroinitializer 809 %negx = fsub nnan nsz arcp <2 x float> <float -0.0, float -0.0>, %x 810 %fabs = select <2 x i1> %gtzero, <2 x float> %x, <2 x float> %negx 811 ret <2 x float> %fabs 812} 813 814define <2 x float> @select_fcmp_nnan_nsz_ogt_zero_unary_fneg(<2 x float> %x) { 815; CHECK-LABEL: @select_fcmp_nnan_nsz_ogt_zero_unary_fneg( 816; CHECK-NEXT: [[GTZERO:%.*]] = fcmp ogt <2 x float> [[X:%.*]], zeroinitializer 817; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan nsz arcp <2 x float> [[X]] 818; CHECK-NEXT: [[FABS:%.*]] = select nnan <2 x i1> [[GTZERO]], <2 x float> [[X]], <2 x float> [[NEGX]] 819; CHECK-NEXT: ret <2 x float> [[FABS]] 820; 821 %gtzero = fcmp ogt <2 x float> %x, zeroinitializer 822 %negx = fneg nnan nsz arcp <2 x float> %x 823 %fabs = select <2 x i1> %gtzero, <2 x float> %x, <2 x float> %negx 824 ret <2 x float> %fabs 825} 826 827; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically. 828 829define <2 x float> @select_fcmp_nnan_nsz_ugt_zero_unary_fneg(<2 x float> %x) { 830; CHECK-LABEL: @select_fcmp_nnan_nsz_ugt_zero_unary_fneg( 831; CHECK-NEXT: [[GTZERO:%.*]] = fcmp ugt <2 x float> [[X:%.*]], zeroinitializer 832; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan nsz arcp <2 x float> [[X]] 833; CHECK-NEXT: [[FABS:%.*]] = select nnan <2 x i1> [[GTZERO]], <2 x float> [[X]], <2 x float> [[NEGX]] 834; CHECK-NEXT: ret <2 x float> [[FABS]] 835; 836 %gtzero = fcmp ugt <2 x float> %x, zeroinitializer 837 %negx = fneg nnan nsz arcp <2 x float> %x 838 %fabs = select <2 x i1> %gtzero, <2 x float> %x, <2 x float> %negx 839 ret <2 x float> %fabs 840} 841 842; X > -0.0 ? X : (0.0 - X) --> fabs(X) 843 844define half @select_fcmp_nnan_nsz_ogt_negzero(half %x) { 845; CHECK-LABEL: @select_fcmp_nnan_nsz_ogt_negzero( 846; CHECK-NEXT: [[GTZERO:%.*]] = fcmp ogt half [[X:%.*]], 0xH0000 847; CHECK-NEXT: [[NEGX:%.*]] = fneg fast half [[X]] 848; CHECK-NEXT: [[FABS:%.*]] = select nnan ninf i1 [[GTZERO]], half [[X]], half [[NEGX]] 849; CHECK-NEXT: ret half [[FABS]] 850; 851 %gtzero = fcmp ogt half %x, -0.0 852 %negx = fsub fast half 0.0, %x 853 %fabs = select i1 %gtzero, half %x, half %negx 854 ret half %fabs 855} 856 857; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically. 858 859define half @select_fcmp_nnan_nsz_ugt_negzero(half %x) { 860; CHECK-LABEL: @select_fcmp_nnan_nsz_ugt_negzero( 861; CHECK-NEXT: [[GTZERO:%.*]] = fcmp ugt half [[X:%.*]], 0xH0000 862; CHECK-NEXT: [[NEGX:%.*]] = fneg fast half [[X]] 863; CHECK-NEXT: [[FABS:%.*]] = select nnan ninf i1 [[GTZERO]], half [[X]], half [[NEGX]] 864; CHECK-NEXT: ret half [[FABS]] 865; 866 %gtzero = fcmp ugt half %x, -0.0 867 %negx = fsub fast half 0.0, %x 868 %fabs = select i1 %gtzero, half %x, half %negx 869 ret half %fabs 870} 871 872; X > 0.0 ? X : (0.0 - X) --> fabs(X) 873 874define <2 x double> @select_fcmp_nnan_nsz_oge_zero(<2 x double> %x) { 875; CHECK-LABEL: @select_fcmp_nnan_nsz_oge_zero( 876; CHECK-NEXT: [[GEZERO:%.*]] = fcmp oge <2 x double> [[X:%.*]], zeroinitializer 877; CHECK-NEXT: [[NEGX:%.*]] = fneg reassoc nnan nsz <2 x double> [[X]] 878; CHECK-NEXT: [[FABS:%.*]] = select nnan <2 x i1> [[GEZERO]], <2 x double> [[X]], <2 x double> [[NEGX]] 879; CHECK-NEXT: ret <2 x double> [[FABS]] 880; 881 %gezero = fcmp oge <2 x double> %x, zeroinitializer 882 %negx = fsub nnan nsz reassoc <2 x double> <double -0.0, double -0.0>, %x 883 %fabs = select <2 x i1> %gezero, <2 x double> %x, <2 x double> %negx 884 ret <2 x double> %fabs 885} 886 887; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically. 888 889define <2 x double> @select_fcmp_nnan_nsz_uge_zero(<2 x double> %x) { 890; CHECK-LABEL: @select_fcmp_nnan_nsz_uge_zero( 891; CHECK-NEXT: [[GEZERO:%.*]] = fcmp uge <2 x double> [[X:%.*]], zeroinitializer 892; CHECK-NEXT: [[NEGX:%.*]] = fneg reassoc nnan nsz <2 x double> [[X]] 893; CHECK-NEXT: [[FABS:%.*]] = select nnan <2 x i1> [[GEZERO]], <2 x double> [[X]], <2 x double> [[NEGX]] 894; CHECK-NEXT: ret <2 x double> [[FABS]] 895; 896 %gezero = fcmp uge <2 x double> %x, zeroinitializer 897 %negx = fsub nnan nsz reassoc <2 x double> <double -0.0, double -0.0>, %x 898 %fabs = select <2 x i1> %gezero, <2 x double> %x, <2 x double> %negx 899 ret <2 x double> %fabs 900} 901 902define <2 x double> @select_fcmp_nnan_nsz_oge_zero_unary_fneg(<2 x double> %x) { 903; CHECK-LABEL: @select_fcmp_nnan_nsz_oge_zero_unary_fneg( 904; CHECK-NEXT: [[GEZERO:%.*]] = fcmp oge <2 x double> [[X:%.*]], zeroinitializer 905; CHECK-NEXT: [[NEGX:%.*]] = fneg reassoc nnan nsz <2 x double> [[X]] 906; CHECK-NEXT: [[FABS:%.*]] = select nnan <2 x i1> [[GEZERO]], <2 x double> [[X]], <2 x double> [[NEGX]] 907; CHECK-NEXT: ret <2 x double> [[FABS]] 908; 909 %gezero = fcmp oge <2 x double> %x, zeroinitializer 910 %negx = fneg nnan nsz reassoc <2 x double> %x 911 %fabs = select <2 x i1> %gezero, <2 x double> %x, <2 x double> %negx 912 ret <2 x double> %fabs 913} 914 915; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically. 916 917define <2 x double> @select_fcmp_nnan_nsz_uge_zero_unary_fneg(<2 x double> %x) { 918; CHECK-LABEL: @select_fcmp_nnan_nsz_uge_zero_unary_fneg( 919; CHECK-NEXT: [[GEZERO:%.*]] = fcmp uge <2 x double> [[X:%.*]], zeroinitializer 920; CHECK-NEXT: [[NEGX:%.*]] = fneg reassoc nnan nsz <2 x double> [[X]] 921; CHECK-NEXT: [[FABS:%.*]] = select nnan <2 x i1> [[GEZERO]], <2 x double> [[X]], <2 x double> [[NEGX]] 922; CHECK-NEXT: ret <2 x double> [[FABS]] 923; 924 %gezero = fcmp uge <2 x double> %x, zeroinitializer 925 %negx = fneg nnan nsz reassoc <2 x double> %x 926 %fabs = select <2 x i1> %gezero, <2 x double> %x, <2 x double> %negx 927 ret <2 x double> %fabs 928} 929 930; X > -0.0 ? X : (0.0 - X) --> fabs(X) 931 932define half @select_fcmp_nnan_nsz_oge_negzero(half %x) { 933; CHECK-LABEL: @select_fcmp_nnan_nsz_oge_negzero( 934; CHECK-NEXT: [[GEZERO:%.*]] = fcmp oge half [[X:%.*]], 0xH0000 935; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan nsz half [[X]] 936; CHECK-NEXT: [[FABS:%.*]] = select nnan i1 [[GEZERO]], half [[X]], half [[NEGX]] 937; CHECK-NEXT: ret half [[FABS]] 938; 939 %gezero = fcmp oge half %x, -0.0 940 %negx = fsub nnan nsz half -0.0, %x 941 %fabs = select i1 %gezero, half %x, half %negx 942 ret half %fabs 943} 944 945; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically. 946 947define half @select_fcmp_nnan_nsz_uge_negzero(half %x) { 948; CHECK-LABEL: @select_fcmp_nnan_nsz_uge_negzero( 949; CHECK-NEXT: [[GEZERO:%.*]] = fcmp uge half [[X:%.*]], 0xH0000 950; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan nsz half [[X]] 951; CHECK-NEXT: [[FABS:%.*]] = select nnan i1 [[GEZERO]], half [[X]], half [[NEGX]] 952; CHECK-NEXT: ret half [[FABS]] 953; 954 %gezero = fcmp uge half %x, -0.0 955 %negx = fsub nnan nsz half -0.0, %x 956 %fabs = select i1 %gezero, half %x, half %negx 957 ret half %fabs 958} 959 960define half @select_fcmp_nnan_nsz_oge_negzero_unary_fneg(half %x) { 961; CHECK-LABEL: @select_fcmp_nnan_nsz_oge_negzero_unary_fneg( 962; CHECK-NEXT: [[GEZERO:%.*]] = fcmp oge half [[X:%.*]], 0xH0000 963; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan nsz half [[X]] 964; CHECK-NEXT: [[FABS:%.*]] = select nnan i1 [[GEZERO]], half [[X]], half [[NEGX]] 965; CHECK-NEXT: ret half [[FABS]] 966; 967 %gezero = fcmp oge half %x, -0.0 968 %negx = fneg nnan nsz half %x 969 %fabs = select i1 %gezero, half %x, half %negx 970 ret half %fabs 971} 972 973; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically. 974 975define half @select_fcmp_nnan_nsz_uge_negzero_unary_fneg(half %x) { 976; CHECK-LABEL: @select_fcmp_nnan_nsz_uge_negzero_unary_fneg( 977; CHECK-NEXT: [[GEZERO:%.*]] = fcmp uge half [[X:%.*]], 0xH0000 978; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan nsz half [[X]] 979; CHECK-NEXT: [[FABS:%.*]] = select nnan i1 [[GEZERO]], half [[X]], half [[NEGX]] 980; CHECK-NEXT: ret half [[FABS]] 981; 982 %gezero = fcmp uge half %x, -0.0 983 %negx = fneg nnan nsz half %x 984 %fabs = select i1 %gezero, half %x, half %negx 985 ret half %fabs 986} 987 988define float @select_fneg(i1 %c, float %x) { 989; CHECK-LABEL: @select_fneg( 990; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]]) 991; CHECK-NEXT: ret float [[FABS]] 992; 993 %n = fneg float %x 994 %s = select i1 %c, float %n, float %x 995 %fabs = call float @llvm.fabs.f32(float %s) 996 ret float %fabs 997} 998 999define float @select_fneg_use1(i1 %c, float %x) { 1000; CHECK-LABEL: @select_fneg_use1( 1001; CHECK-NEXT: [[N:%.*]] = fneg float [[X:%.*]] 1002; CHECK-NEXT: call void @use(float [[N]]) 1003; CHECK-NEXT: [[FABS:%.*]] = call fast float @llvm.fabs.f32(float [[X]]) 1004; CHECK-NEXT: ret float [[FABS]] 1005; 1006 %n = fneg float %x 1007 call void @use(float %n) 1008 %s = select i1 %c, float %x, float %n 1009 %fabs = call fast float @llvm.fabs.f32(float %s) 1010 ret float %fabs 1011} 1012 1013define float @select_fneg_use2(i1 %c, float %x) { 1014; CHECK-LABEL: @select_fneg_use2( 1015; CHECK-NEXT: [[N:%.*]] = fneg arcp float [[X:%.*]] 1016; CHECK-NEXT: [[S:%.*]] = select i1 [[C:%.*]], float [[N]], float [[X]] 1017; CHECK-NEXT: call void @use(float [[S]]) 1018; CHECK-NEXT: [[FABS:%.*]] = call nnan nsz float @llvm.fabs.f32(float [[X]]) 1019; CHECK-NEXT: ret float [[FABS]] 1020; 1021 %n = fneg arcp float %x 1022 %s = select i1 %c, float %n, float %x 1023 call void @use(float %s) 1024 %fabs = call nnan nsz float @llvm.fabs.f32(float %s) 1025 ret float %fabs 1026} 1027 1028define <2 x float> @select_fneg_vec(<2 x i1> %c, <2 x float> %x) { 1029; CHECK-LABEL: @select_fneg_vec( 1030; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[X:%.*]]) 1031; CHECK-NEXT: ret <2 x float> [[FABS]] 1032; 1033 %n = fneg <2 x float> %x 1034 %s = select fast <2 x i1> %c, <2 x float> %x, <2 x float> %n 1035 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %s) 1036 ret <2 x float> %fabs 1037} 1038 1039define float @test_select_neg_negx_x(float %value) { 1040; CHECK-LABEL: @test_select_neg_negx_x( 1041; CHECK-NEXT: [[VALUE_ADDR_0_I:%.*]] = call float @llvm.fabs.f32(float [[VALUE:%.*]]) 1042; CHECK-NEXT: ret float [[VALUE_ADDR_0_I]] 1043; 1044 %a0 = bitcast float %value to i32 1045 %a1 = icmp slt i32 %a0, 0 1046 %fneg.i = fneg float %value 1047 %value.addr.0.i = select i1 %a1, float %fneg.i, float %value 1048 ret float %value.addr.0.i 1049} 1050 1051define float @test_select_nneg_negx_x(float %value) { 1052; CHECK-LABEL: @test_select_nneg_negx_x( 1053; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[VALUE:%.*]]) 1054; CHECK-NEXT: [[VALUE_ADDR_0_I:%.*]] = fneg float [[TMP1]] 1055; CHECK-NEXT: ret float [[VALUE_ADDR_0_I]] 1056; 1057 %a0 = bitcast float %value to i32 1058 %a1 = icmp sgt i32 %a0, -1 1059 %fneg.i = fneg float %value 1060 %value.addr.0.i = select i1 %a1, float %fneg.i, float %value 1061 ret float %value.addr.0.i 1062} 1063 1064define float @test_select_neg_x_negx(float %value) { 1065; CHECK-LABEL: @test_select_neg_x_negx( 1066; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[VALUE:%.*]]) 1067; CHECK-NEXT: [[VALUE_ADDR_0_I:%.*]] = fneg float [[TMP1]] 1068; CHECK-NEXT: ret float [[VALUE_ADDR_0_I]] 1069; 1070 %a0 = bitcast float %value to i32 1071 %a1 = icmp slt i32 %a0, 0 1072 %fneg.i = fneg float %value 1073 %value.addr.0.i = select i1 %a1, float %value, float %fneg.i 1074 ret float %value.addr.0.i 1075} 1076 1077define float @test_select_nneg_x_negx(float %value) { 1078; CHECK-LABEL: @test_select_nneg_x_negx( 1079; CHECK-NEXT: [[VALUE_ADDR_0_I:%.*]] = call float @llvm.fabs.f32(float [[VALUE:%.*]]) 1080; CHECK-NEXT: ret float [[VALUE_ADDR_0_I]] 1081; 1082 %a0 = bitcast float %value to i32 1083 %a1 = icmp sgt i32 %a0, -1 1084 %fneg.i = fneg float %value 1085 %value.addr.0.i = select i1 %a1, float %value, float %fneg.i 1086 ret float %value.addr.0.i 1087} 1088 1089define float @test_select_neg_negx_x_multiuse1(float %value) { 1090; CHECK-LABEL: @test_select_neg_negx_x_multiuse1( 1091; CHECK-NEXT: [[A0:%.*]] = bitcast float [[VALUE:%.*]] to i32 1092; CHECK-NEXT: [[A1:%.*]] = icmp slt i32 [[A0]], 0 1093; CHECK-NEXT: call void @usebool(i1 [[A1]]) 1094; CHECK-NEXT: [[VALUE_ADDR_0_I:%.*]] = call float @llvm.fabs.f32(float [[VALUE]]) 1095; CHECK-NEXT: ret float [[VALUE_ADDR_0_I]] 1096; 1097 %a0 = bitcast float %value to i32 1098 %a1 = icmp slt i32 %a0, 0 1099 call void @usebool(i1 %a1) 1100 %fneg.i = fneg float %value 1101 %value.addr.0.i = select i1 %a1, float %fneg.i, float %value 1102 ret float %value.addr.0.i 1103} 1104 1105define float @test_select_neg_negx_x_multiuse2(float %value) { 1106; CHECK-LABEL: @test_select_neg_negx_x_multiuse2( 1107; CHECK-NEXT: [[FNEG_I:%.*]] = fneg float [[VALUE:%.*]] 1108; CHECK-NEXT: call void @use(float [[FNEG_I]]) 1109; CHECK-NEXT: [[VALUE_ADDR_0_I:%.*]] = call float @llvm.fabs.f32(float [[VALUE]]) 1110; CHECK-NEXT: ret float [[VALUE_ADDR_0_I]] 1111; 1112 %a0 = bitcast float %value to i32 1113 %a1 = icmp slt i32 %a0, 0 1114 %fneg.i = fneg float %value 1115 call void @use(float %fneg.i) 1116 %value.addr.0.i = select i1 %a1, float %fneg.i, float %value 1117 ret float %value.addr.0.i 1118} 1119 1120define float @test_select_neg_negx_x_multiuse3(float %value) { 1121; CHECK-LABEL: @test_select_neg_negx_x_multiuse3( 1122; CHECK-NEXT: [[A0:%.*]] = bitcast float [[VALUE:%.*]] to i32 1123; CHECK-NEXT: [[A1:%.*]] = icmp slt i32 [[A0]], 0 1124; CHECK-NEXT: call void @usebool(i1 [[A1]]) 1125; CHECK-NEXT: [[FNEG_I:%.*]] = fneg float [[VALUE]] 1126; CHECK-NEXT: call void @use(float [[FNEG_I]]) 1127; CHECK-NEXT: [[VALUE_ADDR_0_I:%.*]] = call float @llvm.fabs.f32(float [[VALUE]]) 1128; CHECK-NEXT: ret float [[VALUE_ADDR_0_I]] 1129; 1130 %a0 = bitcast float %value to i32 1131 %a1 = icmp slt i32 %a0, 0 1132 call void @usebool(i1 %a1) 1133 %fneg.i = fneg float %value 1134 call void @use(float %fneg.i) 1135 %value.addr.0.i = select i1 %a1, float %fneg.i, float %value 1136 ret float %value.addr.0.i 1137} 1138 1139define float @test_select_neg_negx_x_fmf(float %value) { 1140; CHECK-LABEL: @test_select_neg_negx_x_fmf( 1141; CHECK-NEXT: [[VALUE_ADDR_0_I:%.*]] = call nnan ninf nsz float @llvm.fabs.f32(float [[VALUE:%.*]]) 1142; CHECK-NEXT: ret float [[VALUE_ADDR_0_I]] 1143; 1144 %a0 = bitcast float %value to i32 1145 %a1 = icmp slt i32 %a0, 0 1146 %fneg.i = fneg float %value 1147 %value.addr.0.i = select nsz nnan ninf i1 %a1, float %fneg.i, float %value 1148 ret float %value.addr.0.i 1149} 1150 1151define float @test_select_nneg_negx_x_fmf(float %value) { 1152; CHECK-LABEL: @test_select_nneg_negx_x_fmf( 1153; CHECK-NEXT: [[TMP1:%.*]] = call nnan ninf nsz float @llvm.fabs.f32(float [[VALUE:%.*]]) 1154; CHECK-NEXT: [[VALUE_ADDR_0_I:%.*]] = fneg nnan ninf nsz float [[TMP1]] 1155; CHECK-NEXT: ret float [[VALUE_ADDR_0_I]] 1156; 1157 %a0 = bitcast float %value to i32 1158 %a1 = icmp sgt i32 %a0, -1 1159 %fneg.i = fneg float %value 1160 %value.addr.0.i = select nsz nnan ninf i1 %a1, float %fneg.i, float %value 1161 ret float %value.addr.0.i 1162} 1163 1164; Negative tests 1165 1166define float @test_select_nneg_negx_x_multiuse4(float %value) { 1167; CHECK-LABEL: @test_select_nneg_negx_x_multiuse4( 1168; CHECK-NEXT: [[A0:%.*]] = bitcast float [[VALUE:%.*]] to i32 1169; CHECK-NEXT: [[A1:%.*]] = icmp sgt i32 [[A0]], -1 1170; CHECK-NEXT: call void @usebool(i1 [[A1]]) 1171; CHECK-NEXT: [[FNEG_I:%.*]] = fneg float [[VALUE]] 1172; CHECK-NEXT: call void @use(float [[FNEG_I]]) 1173; CHECK-NEXT: [[VALUE_ADDR_0_I:%.*]] = select i1 [[A1]], float [[FNEG_I]], float [[VALUE]] 1174; CHECK-NEXT: ret float [[VALUE_ADDR_0_I]] 1175; 1176 %a0 = bitcast float %value to i32 1177 %a1 = icmp sgt i32 %a0, -1 1178 call void @usebool(i1 %a1) 1179 %fneg.i = fneg float %value 1180 call void @use(float %fneg.i) 1181 %value.addr.0.i = select i1 %a1, float %fneg.i, float %value 1182 ret float %value.addr.0.i 1183} 1184 1185define float @test_select_neg_negx_x_mismatched1(float %value, float %y) { 1186; CHECK-LABEL: @test_select_neg_negx_x_mismatched1( 1187; CHECK-NEXT: [[A0:%.*]] = bitcast float [[Y:%.*]] to i32 1188; CHECK-NEXT: [[A1:%.*]] = icmp slt i32 [[A0]], 0 1189; CHECK-NEXT: [[FNEG_I:%.*]] = fneg float [[VALUE:%.*]] 1190; CHECK-NEXT: [[VALUE_ADDR_0_I:%.*]] = select i1 [[A1]], float [[FNEG_I]], float [[VALUE]] 1191; CHECK-NEXT: ret float [[VALUE_ADDR_0_I]] 1192; 1193 %a0 = bitcast float %y to i32 1194 %a1 = icmp slt i32 %a0, 0 1195 %fneg.i = fneg float %value 1196 %value.addr.0.i = select i1 %a1, float %fneg.i, float %value 1197 ret float %value.addr.0.i 1198} 1199 1200define float @test_select_neg_negx_x_mismatched2(float %value, float %y) { 1201; CHECK-LABEL: @test_select_neg_negx_x_mismatched2( 1202; CHECK-NEXT: [[A0:%.*]] = bitcast float [[VALUE:%.*]] to i32 1203; CHECK-NEXT: [[A1:%.*]] = icmp slt i32 [[A0]], 0 1204; CHECK-NEXT: [[FNEG_I:%.*]] = fneg float [[Y:%.*]] 1205; CHECK-NEXT: [[VALUE_ADDR_0_I:%.*]] = select i1 [[A1]], float [[FNEG_I]], float [[VALUE]] 1206; CHECK-NEXT: ret float [[VALUE_ADDR_0_I]] 1207; 1208 %a0 = bitcast float %value to i32 1209 %a1 = icmp slt i32 %a0, 0 1210 %fneg.i = fneg float %y 1211 %value.addr.0.i = select i1 %a1, float %fneg.i, float %value 1212 ret float %value.addr.0.i 1213} 1214 1215define float @test_select_neg_negx_x_mismatched3(float %value, float %y) { 1216; CHECK-LABEL: @test_select_neg_negx_x_mismatched3( 1217; CHECK-NEXT: [[A0:%.*]] = bitcast float [[VALUE:%.*]] to i32 1218; CHECK-NEXT: [[A1:%.*]] = icmp slt i32 [[A0]], 0 1219; CHECK-NEXT: [[FNEG_I:%.*]] = fneg float [[VALUE]] 1220; CHECK-NEXT: [[VALUE_ADDR_0_I:%.*]] = select i1 [[A1]], float [[FNEG_I]], float [[Y:%.*]] 1221; CHECK-NEXT: ret float [[VALUE_ADDR_0_I]] 1222; 1223 %a0 = bitcast float %value to i32 1224 %a1 = icmp slt i32 %a0, 0 1225 %fneg.i = fneg float %value 1226 %value.addr.0.i = select i1 %a1, float %fneg.i, float %y 1227 ret float %value.addr.0.i 1228} 1229 1230define <2 x float> @test_select_neg_negx_x_wrong_type(<2 x float> %value) { 1231; CHECK-LABEL: @test_select_neg_negx_x_wrong_type( 1232; CHECK-NEXT: [[A0:%.*]] = bitcast <2 x float> [[VALUE:%.*]] to i64 1233; CHECK-NEXT: [[A1:%.*]] = icmp slt i64 [[A0]], 0 1234; CHECK-NEXT: [[FNEG_I:%.*]] = fneg <2 x float> [[VALUE]] 1235; CHECK-NEXT: [[VALUE_ADDR_0_I:%.*]] = select i1 [[A1]], <2 x float> [[FNEG_I]], <2 x float> [[VALUE]] 1236; CHECK-NEXT: ret <2 x float> [[VALUE_ADDR_0_I]] 1237; 1238 %a0 = bitcast <2 x float> %value to i64 1239 %a1 = icmp slt i64 %a0, 0 1240 %fneg.i = fneg <2 x float> %value 1241 %value.addr.0.i = select i1 %a1, <2 x float> %fneg.i, <2 x float> %value 1242 ret <2 x float> %value.addr.0.i 1243} 1244