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) 18 19define float @replace_fabs_call_f32(float %x) { 20; CHECK-LABEL: @replace_fabs_call_f32( 21; CHECK-NEXT: [[FABSF:%.*]] = tail call float @llvm.fabs.f32(float [[X:%.*]]) 22; CHECK-NEXT: ret float [[FABSF]] 23; 24 %fabsf = tail call float @fabsf(float %x) 25 ret float %fabsf 26} 27 28define double @replace_fabs_call_f64(double %x) { 29; CHECK-LABEL: @replace_fabs_call_f64( 30; CHECK-NEXT: [[FABS:%.*]] = tail call double @llvm.fabs.f64(double [[X:%.*]]) 31; CHECK-NEXT: ret double [[FABS]] 32; 33 %fabs = tail call double @fabs(double %x) 34 ret double %fabs 35} 36 37define fp128 @replace_fabs_call_f128(fp128 %x) { 38; CHECK-LABEL: @replace_fabs_call_f128( 39; CHECK-NEXT: [[FABSL:%.*]] = tail call fp128 @llvm.fabs.f128(fp128 [[X:%.*]]) 40; CHECK-NEXT: ret fp128 [[FABSL]] 41; 42 %fabsl = tail call fp128 @fabsl(fp128 %x) 43 ret fp128 %fabsl 44} 45 46; Make sure fast math flags are preserved when replacing the libcall. 47define float @fmf_replace_fabs_call_f32(float %x) { 48; CHECK-LABEL: @fmf_replace_fabs_call_f32( 49; CHECK-NEXT: [[FABSF:%.*]] = tail call nnan float @llvm.fabs.f32(float [[X:%.*]]) 50; CHECK-NEXT: ret float [[FABSF]] 51; 52 %fabsf = tail call nnan float @fabsf(float %x) 53 ret float %fabsf 54} 55 56; Make sure all intrinsic calls are eliminated when the input is known 57; positive. 58 59; The fabs cannot be eliminated because %x may be a NaN 60 61define float @square_fabs_intrinsic_f32(float %x) { 62; CHECK-LABEL: @square_fabs_intrinsic_f32( 63; CHECK-NEXT: [[MUL:%.*]] = fmul float [[X:%.*]], [[X]] 64; CHECK-NEXT: [[FABSF:%.*]] = tail call float @llvm.fabs.f32(float [[MUL]]) 65; CHECK-NEXT: ret float [[FABSF]] 66; 67 %mul = fmul float %x, %x 68 %fabsf = tail call float @llvm.fabs.f32(float %mul) 69 ret float %fabsf 70} 71 72define double @square_fabs_intrinsic_f64(double %x) { 73; CHECK-LABEL: @square_fabs_intrinsic_f64( 74; CHECK-NEXT: [[MUL:%.*]] = fmul double [[X:%.*]], [[X]] 75; CHECK-NEXT: [[FABS:%.*]] = tail call double @llvm.fabs.f64(double [[MUL]]) 76; CHECK-NEXT: ret double [[FABS]] 77; 78 %mul = fmul double %x, %x 79 %fabs = tail call double @llvm.fabs.f64(double %mul) 80 ret double %fabs 81} 82 83define fp128 @square_fabs_intrinsic_f128(fp128 %x) { 84; CHECK-LABEL: @square_fabs_intrinsic_f128( 85; CHECK-NEXT: [[MUL:%.*]] = fmul fp128 [[X:%.*]], [[X]] 86; CHECK-NEXT: [[FABSL:%.*]] = tail call fp128 @llvm.fabs.f128(fp128 [[MUL]]) 87; CHECK-NEXT: ret fp128 [[FABSL]] 88; 89 %mul = fmul fp128 %x, %x 90 %fabsl = tail call fp128 @llvm.fabs.f128(fp128 %mul) 91 ret fp128 %fabsl 92} 93 94define float @square_nnan_fabs_intrinsic_f32(float %x) { 95; CHECK-LABEL: @square_nnan_fabs_intrinsic_f32( 96; CHECK-NEXT: [[MUL:%.*]] = fmul nnan float [[X:%.*]], [[X]] 97; CHECK-NEXT: ret float [[MUL]] 98; 99 %mul = fmul nnan float %x, %x 100 %fabsf = call float @llvm.fabs.f32(float %mul) 101 ret float %fabsf 102} 103 104; Shrinking a library call to a smaller type should not be inhibited by nor inhibit the square optimization. 105 106define float @square_fabs_shrink_call1(float %x) { 107; CHECK-LABEL: @square_fabs_shrink_call1( 108; CHECK-NEXT: [[TMP1:%.*]] = fmul float [[X:%.*]], [[X]] 109; CHECK-NEXT: [[TRUNC:%.*]] = call float @llvm.fabs.f32(float [[TMP1]]) 110; CHECK-NEXT: ret float [[TRUNC]] 111; 112 %ext = fpext float %x to double 113 %sq = fmul double %ext, %ext 114 %fabs = call double @fabs(double %sq) 115 %trunc = fptrunc double %fabs to float 116 ret float %trunc 117} 118 119define float @square_fabs_shrink_call2(float %x) { 120; CHECK-LABEL: @square_fabs_shrink_call2( 121; CHECK-NEXT: [[SQ:%.*]] = fmul float [[X:%.*]], [[X]] 122; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[SQ]]) 123; CHECK-NEXT: ret float [[TMP1]] 124; 125 %sq = fmul float %x, %x 126 %ext = fpext float %sq to double 127 %fabs = call double @fabs(double %ext) 128 %trunc = fptrunc double %fabs to float 129 ret float %trunc 130} 131 132define float @fabs_select_constant_negative_positive(i32 %c) { 133; CHECK-LABEL: @fabs_select_constant_negative_positive( 134; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 135; CHECK-NEXT: [[FABS:%.*]] = select i1 [[CMP]], float 1.000000e+00, float 2.000000e+00 136; CHECK-NEXT: ret float [[FABS]] 137; 138 %cmp = icmp eq i32 %c, 0 139 %select = select i1 %cmp, float -1.0, float 2.0 140 %fabs = call float @llvm.fabs.f32(float %select) 141 ret float %fabs 142} 143 144define float @fabs_select_constant_positive_negative(i32 %c) { 145; CHECK-LABEL: @fabs_select_constant_positive_negative( 146; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 147; CHECK-NEXT: [[FABS:%.*]] = select i1 [[CMP]], float 1.000000e+00, float 2.000000e+00 148; CHECK-NEXT: ret float [[FABS]] 149; 150 %cmp = icmp eq i32 %c, 0 151 %select = select i1 %cmp, float 1.0, float -2.0 152 %fabs = call float @llvm.fabs.f32(float %select) 153 ret float %fabs 154} 155 156define float @fabs_select_constant_negative_negative(i32 %c) { 157; CHECK-LABEL: @fabs_select_constant_negative_negative( 158; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 159; CHECK-NEXT: [[FABS:%.*]] = select i1 [[CMP]], float 1.000000e+00, float 2.000000e+00 160; CHECK-NEXT: ret float [[FABS]] 161; 162 %cmp = icmp eq i32 %c, 0 163 %select = select i1 %cmp, float -1.0, float -2.0 164 %fabs = call float @llvm.fabs.f32(float %select) 165 ret float %fabs 166} 167 168define float @fabs_select_constant_neg0(i32 %c) { 169; CHECK-LABEL: @fabs_select_constant_neg0( 170; CHECK-NEXT: ret float 0.000000e+00 171; 172 %cmp = icmp eq i32 %c, 0 173 %select = select i1 %cmp, float -0.0, float 0.0 174 %fabs = call float @llvm.fabs.f32(float %select) 175 ret float %fabs 176} 177 178define float @fabs_select_var_constant_negative(i32 %c, float %x) { 179; CHECK-LABEL: @fabs_select_var_constant_negative( 180; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 181; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float [[X:%.*]], float -1.000000e+00 182; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) 183; CHECK-NEXT: ret float [[FABS]] 184; 185 %cmp = icmp eq i32 %c, 0 186 %select = select i1 %cmp, float %x, float -1.0 187 %fabs = call float @llvm.fabs.f32(float %select) 188 ret float %fabs 189} 190 191; The fabs cannot be eliminated because %x may be a NaN 192 193define float @square_fma_fabs_intrinsic_f32(float %x) { 194; CHECK-LABEL: @square_fma_fabs_intrinsic_f32( 195; CHECK-NEXT: [[FMA:%.*]] = call float @llvm.fma.f32(float [[X:%.*]], float [[X]], float 1.000000e+00) 196; CHECK-NEXT: [[FABSF:%.*]] = call float @llvm.fabs.f32(float [[FMA]]) 197; CHECK-NEXT: ret float [[FABSF]] 198; 199 %fma = call float @llvm.fma.f32(float %x, float %x, float 1.0) 200 %fabsf = call float @llvm.fabs.f32(float %fma) 201 ret float %fabsf 202} 203 204; The fabs cannot be eliminated because %x may be a NaN 205 206define float @square_nnan_fma_fabs_intrinsic_f32(float %x) { 207; CHECK-LABEL: @square_nnan_fma_fabs_intrinsic_f32( 208; CHECK-NEXT: [[FMA:%.*]] = call nnan float @llvm.fma.f32(float [[X:%.*]], float [[X]], float 1.000000e+00) 209; CHECK-NEXT: ret float [[FMA]] 210; 211 %fma = call nnan float @llvm.fma.f32(float %x, float %x, float 1.0) 212 %fabsf = call float @llvm.fabs.f32(float %fma) 213 ret float %fabsf 214} 215 216define float @square_fmuladd_fabs_intrinsic_f32(float %x) { 217; CHECK-LABEL: @square_fmuladd_fabs_intrinsic_f32( 218; CHECK-NEXT: [[FMULADD:%.*]] = call float @llvm.fmuladd.f32(float [[X:%.*]], float [[X]], float 1.000000e+00) 219; CHECK-NEXT: [[FABSF:%.*]] = call float @llvm.fabs.f32(float [[FMULADD]]) 220; CHECK-NEXT: ret float [[FABSF]] 221; 222 %fmuladd = call float @llvm.fmuladd.f32(float %x, float %x, float 1.0) 223 %fabsf = call float @llvm.fabs.f32(float %fmuladd) 224 ret float %fabsf 225} 226 227define float @square_nnan_fmuladd_fabs_intrinsic_f32(float %x) { 228; CHECK-LABEL: @square_nnan_fmuladd_fabs_intrinsic_f32( 229; CHECK-NEXT: [[FMULADD:%.*]] = call nnan float @llvm.fmuladd.f32(float [[X:%.*]], float [[X]], float 1.000000e+00) 230; CHECK-NEXT: ret float [[FMULADD]] 231; 232 %fmuladd = call nnan float @llvm.fmuladd.f32(float %x, float %x, float 1.0) 233 %fabsf = call float @llvm.fabs.f32(float %fmuladd) 234 ret float %fabsf 235} 236 237; Don't introduce a second fpext 238 239define double @multi_use_fabs_fpext(float %x) { 240; CHECK-LABEL: @multi_use_fabs_fpext( 241; CHECK-NEXT: [[FPEXT:%.*]] = fpext float [[X:%.*]] to double 242; CHECK-NEXT: [[FABS:%.*]] = call double @llvm.fabs.f64(double [[FPEXT]]) 243; CHECK-NEXT: store volatile double [[FPEXT]], double* undef, align 8 244; CHECK-NEXT: ret double [[FABS]] 245; 246 %fpext = fpext float %x to double 247 %fabs = call double @llvm.fabs.f64(double %fpext) 248 store volatile double %fpext, double* undef 249 ret double %fabs 250} 251 252; X <= 0.0 ? (0.0 - X) : X --> fabs(X) 253 254define double @select_fcmp_ole_zero(double %x) { 255; CHECK-LABEL: @select_fcmp_ole_zero( 256; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.fabs.f64(double [[X:%.*]]) 257; CHECK-NEXT: ret double [[TMP1]] 258; 259 %lezero = fcmp ole double %x, 0.0 260 %negx = fsub double 0.0, %x 261 %fabs = select i1 %lezero, double %negx, double %x 262 ret double %fabs 263} 264 265define double @select_fcmp_nnan_ole_zero(double %x) { 266; CHECK-LABEL: @select_fcmp_nnan_ole_zero( 267; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.fabs.f64(double [[X:%.*]]) 268; CHECK-NEXT: ret double [[TMP1]] 269; 270 %lezero = fcmp ole double %x, 0.0 271 %negx = fsub nnan double 0.0, %x 272 %fabs = select i1 %lezero, double %negx, double %x 273 ret double %fabs 274} 275 276define double @select_nnan_fcmp_nnan_ole_zero(double %x) { 277; CHECK-LABEL: @select_nnan_fcmp_nnan_ole_zero( 278; CHECK-NEXT: [[TMP1:%.*]] = call nnan double @llvm.fabs.f64(double [[X:%.*]]) 279; CHECK-NEXT: ret double [[TMP1]] 280; 281 %lezero = fcmp ole double %x, 0.0 282 %negx = fsub nnan double 0.0, %x 283 %fabs = select nnan i1 %lezero, double %negx, double %x 284 ret double %fabs 285} 286 287; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically. 288 289define double @select_fcmp_nnan_ule_zero(double %x) { 290; CHECK-LABEL: @select_fcmp_nnan_ule_zero( 291; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.fabs.f64(double [[X:%.*]]) 292; CHECK-NEXT: ret double [[TMP1]] 293; 294 %lezero = fcmp ule double %x, 0.0 295 %negx = fsub nnan double 0.0, %x 296 %fabs = select i1 %lezero, double %negx, double %x 297 ret double %fabs 298} 299 300; Negative test - wrong predicate. 301 302define double @select_fcmp_nnan_olt_zero(double %x) { 303; CHECK-LABEL: @select_fcmp_nnan_olt_zero( 304; CHECK-NEXT: [[LEZERO:%.*]] = fcmp olt double [[X:%.*]], 0.000000e+00 305; CHECK-NEXT: [[NEGX:%.*]] = fsub nnan double 0.000000e+00, [[X]] 306; CHECK-NEXT: [[FABS:%.*]] = select i1 [[LEZERO]], double [[NEGX]], double [[X]] 307; CHECK-NEXT: ret double [[FABS]] 308; 309 %lezero = fcmp olt double %x, 0.0 310 %negx = fsub nnan double 0.0, %x 311 %fabs = select i1 %lezero, double %negx, double %x 312 ret double %fabs 313} 314 315; X <= -0.0 ? (0.0 - X) : X --> fabs(X) 316 317define <2 x float> @select_fcmp_nnan_ole_negzero(<2 x float> %x) { 318; CHECK-LABEL: @select_fcmp_nnan_ole_negzero( 319; CHECK-NEXT: [[TMP1:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[X:%.*]]) 320; CHECK-NEXT: ret <2 x float> [[TMP1]] 321; 322 %lezero = fcmp ole <2 x float> %x, <float -0.0, float -0.0> 323 %negx = fsub nnan <2 x float> <float 0.0, float undef>, %x 324 %fabs = select <2 x i1> %lezero, <2 x float> %negx, <2 x float> %x 325 ret <2 x float> %fabs 326} 327 328define <2 x float> @select_nnan_fcmp_nnan_ole_negzero(<2 x float> %x) { 329; CHECK-LABEL: @select_nnan_fcmp_nnan_ole_negzero( 330; CHECK-NEXT: [[TMP1:%.*]] = call nnan <2 x float> @llvm.fabs.v2f32(<2 x float> [[X:%.*]]) 331; CHECK-NEXT: ret <2 x float> [[TMP1]] 332; 333 %lezero = fcmp ole <2 x float> %x, <float -0.0, float -0.0> 334 %negx = fsub nnan <2 x float> <float 0.0, float undef>, %x 335 %fabs = select nnan <2 x i1> %lezero, <2 x float> %negx, <2 x float> %x 336 ret <2 x float> %fabs 337} 338 339; X > 0.0 ? X : (0.0 - X) --> fabs(X) 340 341define fp128 @select_fcmp_ogt_zero(fp128 %x) { 342; CHECK-LABEL: @select_fcmp_ogt_zero( 343; CHECK-NEXT: [[TMP1:%.*]] = call fp128 @llvm.fabs.f128(fp128 [[X:%.*]]) 344; CHECK-NEXT: ret fp128 [[TMP1]] 345; 346 %gtzero = fcmp ogt fp128 %x, zeroinitializer 347 %negx = fsub fp128 zeroinitializer, %x 348 %fabs = select i1 %gtzero, fp128 %x, fp128 %negx 349 ret fp128 %fabs 350} 351 352define float @select_fcmp_ogt_fneg(float %a) { 353; CHECK-LABEL: @select_fcmp_ogt_fneg( 354; CHECK-NEXT: [[TMP1:%.*]] = call nsz float @llvm.fabs.f32(float [[A:%.*]]) 355; CHECK-NEXT: ret float [[TMP1]] 356; 357 %fneg = fneg float %a 358 %cmp = fcmp ogt float %a, %fneg 359 %r = select nsz i1 %cmp, float %a, float %fneg 360 ret float %r 361} 362 363define fp128 @select_fcmp_nnan_ogt_zero(fp128 %x) { 364; CHECK-LABEL: @select_fcmp_nnan_ogt_zero( 365; CHECK-NEXT: [[TMP1:%.*]] = call fp128 @llvm.fabs.f128(fp128 [[X:%.*]]) 366; CHECK-NEXT: ret fp128 [[TMP1]] 367; 368 %gtzero = fcmp ogt fp128 %x, zeroinitializer 369 %negx = fsub nnan fp128 zeroinitializer, %x 370 %fabs = select i1 %gtzero, fp128 %x, fp128 %negx 371 ret fp128 %fabs 372} 373 374define fp128 @select_nnan_fcmp_nnan_ogt_zero(fp128 %x) { 375; CHECK-LABEL: @select_nnan_fcmp_nnan_ogt_zero( 376; CHECK-NEXT: [[TMP1:%.*]] = call nnan fp128 @llvm.fabs.f128(fp128 [[X:%.*]]) 377; CHECK-NEXT: ret fp128 [[TMP1]] 378; 379 %gtzero = fcmp ogt fp128 %x, zeroinitializer 380 %negx = fsub nnan fp128 zeroinitializer, %x 381 %fabs = select nnan i1 %gtzero, fp128 %x, fp128 %negx 382 ret fp128 %fabs 383} 384 385; X > -0.0 ? X : (0.0 - X) --> fabs(X) 386 387define half @select_fcmp_nnan_ogt_negzero(half %x) { 388; CHECK-LABEL: @select_fcmp_nnan_ogt_negzero( 389; CHECK-NEXT: [[TMP1:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) 390; CHECK-NEXT: ret half [[TMP1]] 391; 392 %gtzero = fcmp ogt half %x, -0.0 393 %negx = fsub nnan half 0.0, %x 394 %fabs = select i1 %gtzero, half %x, half %negx 395 ret half %fabs 396} 397 398define half @select_nnan_fcmp_nnan_ogt_negzero(half %x) { 399; CHECK-LABEL: @select_nnan_fcmp_nnan_ogt_negzero( 400; CHECK-NEXT: [[TMP1:%.*]] = call nnan half @llvm.fabs.f16(half [[X:%.*]]) 401; CHECK-NEXT: ret half [[TMP1]] 402; 403 %gtzero = fcmp ogt half %x, -0.0 404 %negx = fsub nnan half 0.0, %x 405 %fabs = select nnan i1 %gtzero, half %x, half %negx 406 ret half %fabs 407} 408 409; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically. 410 411define half @select_fcmp_nnan_ugt_negzero(half %x) { 412; CHECK-LABEL: @select_fcmp_nnan_ugt_negzero( 413; CHECK-NEXT: [[TMP1:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) 414; CHECK-NEXT: ret half [[TMP1]] 415; 416 %gtzero = fcmp ugt half %x, -0.0 417 %negx = fsub nnan half 0.0, %x 418 %fabs = select i1 %gtzero, half %x, half %negx 419 ret half %fabs 420} 421 422; Negative test - wrong predicate. 423 424define half @select_fcmp_nnan_oge_negzero(half %x) { 425; CHECK-LABEL: @select_fcmp_nnan_oge_negzero( 426; CHECK-NEXT: [[GTZERO:%.*]] = fcmp oge half [[X:%.*]], 0xH0000 427; CHECK-NEXT: [[NEGX:%.*]] = fsub nnan half 0xH0000, [[X]] 428; CHECK-NEXT: [[FABS:%.*]] = select i1 [[GTZERO]], half [[X]], half [[NEGX]] 429; CHECK-NEXT: ret half [[FABS]] 430; 431 %gtzero = fcmp oge half %x, -0.0 432 %negx = fsub nnan half 0.0, %x 433 %fabs = select i1 %gtzero, half %x, half %negx 434 ret half %fabs 435} 436 437; X < 0.0 ? -X : X --> fabs(X) 438 439define double @select_fcmp_olt_zero_unary_fneg(double %x) { 440; CHECK-LABEL: @select_fcmp_olt_zero_unary_fneg( 441; CHECK-NEXT: [[TMP1:%.*]] = call nsz double @llvm.fabs.f64(double [[X:%.*]]) 442; CHECK-NEXT: ret double [[TMP1]] 443; 444 %ltzero = fcmp olt double %x, 0.0 445 %negx = fneg double %x 446 %fabs = select nsz i1 %ltzero, double %negx, double %x 447 ret double %fabs 448} 449 450define double @select_fcmp_nnan_nsz_olt_zero(double %x) { 451; CHECK-LABEL: @select_fcmp_nnan_nsz_olt_zero( 452; CHECK-NEXT: [[LTZERO:%.*]] = fcmp olt double [[X:%.*]], 0.000000e+00 453; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan nsz double [[X]] 454; CHECK-NEXT: [[FABS:%.*]] = select i1 [[LTZERO]], double [[NEGX]], double [[X]] 455; CHECK-NEXT: ret double [[FABS]] 456; 457 %ltzero = fcmp olt double %x, 0.0 458 %negx = fsub nnan nsz double -0.0, %x 459 %fabs = select i1 %ltzero, double %negx, double %x 460 ret double %fabs 461} 462 463define double @select_nnan_nsz_fcmp_nnan_nsz_olt_zero(double %x) { 464; CHECK-LABEL: @select_nnan_nsz_fcmp_nnan_nsz_olt_zero( 465; CHECK-NEXT: [[TMP1:%.*]] = call nnan nsz double @llvm.fabs.f64(double [[X:%.*]]) 466; CHECK-NEXT: ret double [[TMP1]] 467; 468 %ltzero = fcmp olt double %x, 0.0 469 %negx = fsub nnan nsz double -0.0, %x 470 %fabs = select nnan nsz i1 %ltzero, double %negx, double %x 471 ret double %fabs 472} 473 474; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically. 475 476define double @select_fcmp_nnan_nsz_ult_zero(double %x) { 477; CHECK-LABEL: @select_fcmp_nnan_nsz_ult_zero( 478; CHECK-NEXT: [[LTZERO:%.*]] = fcmp ult double [[X:%.*]], 0.000000e+00 479; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan nsz double [[X]] 480; CHECK-NEXT: [[FABS:%.*]] = select i1 [[LTZERO]], double [[NEGX]], double [[X]] 481; CHECK-NEXT: ret double [[FABS]] 482; 483 %ltzero = fcmp ult double %x, 0.0 484 %negx = fsub nnan nsz double -0.0, %x 485 %fabs = select i1 %ltzero, double %negx, double %x 486 ret double %fabs 487} 488 489define double @select_fcmp_nnan_nsz_olt_zero_unary_fneg(double %x) { 490; CHECK-LABEL: @select_fcmp_nnan_nsz_olt_zero_unary_fneg( 491; CHECK-NEXT: [[LTZERO:%.*]] = fcmp olt double [[X:%.*]], 0.000000e+00 492; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan nsz double [[X]] 493; CHECK-NEXT: [[FABS:%.*]] = select i1 [[LTZERO]], double [[NEGX]], double [[X]] 494; CHECK-NEXT: ret double [[FABS]] 495; 496 %ltzero = fcmp olt double %x, 0.0 497 %negx = fneg nnan nsz double %x 498 %fabs = select i1 %ltzero, double %negx, double %x 499 ret double %fabs 500} 501 502; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically. 503 504define double @select_fcmp_nnan_nsz_ult_zero_unary_fneg(double %x) { 505; CHECK-LABEL: @select_fcmp_nnan_nsz_ult_zero_unary_fneg( 506; CHECK-NEXT: [[LTZERO:%.*]] = fcmp ult double [[X:%.*]], 0.000000e+00 507; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan nsz double [[X]] 508; CHECK-NEXT: [[FABS:%.*]] = select i1 [[LTZERO]], double [[NEGX]], double [[X]] 509; CHECK-NEXT: ret double [[FABS]] 510; 511 %ltzero = fcmp ult double %x, 0.0 512 %negx = fneg nnan nsz double %x 513 %fabs = select i1 %ltzero, double %negx, double %x 514 ret double %fabs 515} 516 517; X < -0.0 ? -X : X --> fabs(X) 518 519define float @select_fcmp_nnan_nsz_olt_negzero(float %x) { 520; CHECK-LABEL: @select_fcmp_nnan_nsz_olt_negzero( 521; CHECK-NEXT: [[LTZERO:%.*]] = fcmp olt float [[X:%.*]], 0.000000e+00 522; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan ninf nsz float [[X]] 523; CHECK-NEXT: [[FABS:%.*]] = select i1 [[LTZERO]], float [[NEGX]], float [[X]] 524; CHECK-NEXT: ret float [[FABS]] 525; 526 %ltzero = fcmp olt float %x, -0.0 527 %negx = fsub nnan ninf nsz float -0.0, %x 528 %fabs = select i1 %ltzero, float %negx, float %x 529 ret float %fabs 530} 531 532define float @select_nnan_ninf_nsz_fcmp_nnan_nsz_olt_negzero(float %x) { 533; CHECK-LABEL: @select_nnan_ninf_nsz_fcmp_nnan_nsz_olt_negzero( 534; CHECK-NEXT: [[TMP1:%.*]] = call nnan ninf nsz float @llvm.fabs.f32(float [[X:%.*]]) 535; CHECK-NEXT: ret float [[TMP1]] 536; 537 %ltzero = fcmp olt float %x, -0.0 538 %negx = fsub nnan nsz float -0.0, %x 539 %fabs = select nnan ninf nsz i1 %ltzero, float %negx, float %x 540 ret float %fabs 541} 542 543; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically. 544 545define float @select_fcmp_nnan_nsz_ult_negzero(float %x) { 546; CHECK-LABEL: @select_fcmp_nnan_nsz_ult_negzero( 547; CHECK-NEXT: [[LTZERO:%.*]] = fcmp ult float [[X:%.*]], 0.000000e+00 548; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan ninf nsz float [[X]] 549; CHECK-NEXT: [[FABS:%.*]] = select i1 [[LTZERO]], float [[NEGX]], float [[X]] 550; CHECK-NEXT: ret float [[FABS]] 551; 552 %ltzero = fcmp ult float %x, -0.0 553 %negx = fsub nnan ninf nsz float -0.0, %x 554 %fabs = select i1 %ltzero, float %negx, float %x 555 ret float %fabs 556} 557 558define float @select_fcmp_nnan_nsz_olt_negzero_unary_fneg(float %x) { 559; CHECK-LABEL: @select_fcmp_nnan_nsz_olt_negzero_unary_fneg( 560; CHECK-NEXT: [[LTZERO:%.*]] = fcmp olt float [[X:%.*]], 0.000000e+00 561; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan ninf nsz float [[X]] 562; CHECK-NEXT: [[FABS:%.*]] = select i1 [[LTZERO]], float [[NEGX]], float [[X]] 563; CHECK-NEXT: ret float [[FABS]] 564; 565 %ltzero = fcmp olt float %x, -0.0 566 %negx = fneg nnan ninf nsz float %x 567 %fabs = select i1 %ltzero, float %negx, float %x 568 ret float %fabs 569} 570 571; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically. 572 573define float @select_fcmp_nnan_nsz_ult_negzero_unary_fneg(float %x) { 574; CHECK-LABEL: @select_fcmp_nnan_nsz_ult_negzero_unary_fneg( 575; CHECK-NEXT: [[LTZERO:%.*]] = fcmp ult float [[X:%.*]], 0.000000e+00 576; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan ninf nsz float [[X]] 577; CHECK-NEXT: [[FABS:%.*]] = select i1 [[LTZERO]], float [[NEGX]], float [[X]] 578; CHECK-NEXT: ret float [[FABS]] 579; 580 %ltzero = fcmp ult float %x, -0.0 581 %negx = fneg nnan ninf nsz float %x 582 %fabs = select i1 %ltzero, float %negx, float %x 583 ret float %fabs 584} 585 586; X <= 0.0 ? -X : X --> fabs(X) 587 588define double @select_fcmp_nnan_nsz_ole_zero(double %x) { 589; CHECK-LABEL: @select_fcmp_nnan_nsz_ole_zero( 590; CHECK-NEXT: [[LEZERO:%.*]] = fcmp ole double [[X:%.*]], 0.000000e+00 591; CHECK-NEXT: [[NEGX:%.*]] = fneg fast double [[X]] 592; CHECK-NEXT: [[FABS:%.*]] = select i1 [[LEZERO]], double [[NEGX]], double [[X]] 593; CHECK-NEXT: ret double [[FABS]] 594; 595 %lezero = fcmp ole double %x, 0.0 596 %negx = fsub fast double -0.0, %x 597 %fabs = select i1 %lezero, double %negx, double %x 598 ret double %fabs 599} 600 601define double @select_fast_fcmp_nnan_nsz_ole_zero(double %x) { 602; CHECK-LABEL: @select_fast_fcmp_nnan_nsz_ole_zero( 603; CHECK-NEXT: [[TMP1:%.*]] = call fast double @llvm.fabs.f64(double [[X:%.*]]) 604; CHECK-NEXT: ret double [[TMP1]] 605; 606 %lezero = fcmp ole double %x, 0.0 607 %negx = fsub nnan nsz double -0.0, %x 608 %fabs = select fast i1 %lezero, double %negx, double %x 609 ret double %fabs 610} 611 612; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically. 613 614define double @select_fcmp_nnan_nsz_ule_zero(double %x) { 615; CHECK-LABEL: @select_fcmp_nnan_nsz_ule_zero( 616; CHECK-NEXT: [[LEZERO:%.*]] = fcmp ule double [[X:%.*]], 0.000000e+00 617; CHECK-NEXT: [[NEGX:%.*]] = fneg fast double [[X]] 618; CHECK-NEXT: [[FABS:%.*]] = select i1 [[LEZERO]], double [[NEGX]], double [[X]] 619; CHECK-NEXT: ret double [[FABS]] 620; 621 %lezero = fcmp ule double %x, 0.0 622 %negx = fsub fast double -0.0, %x 623 %fabs = select i1 %lezero, double %negx, double %x 624 ret double %fabs 625} 626 627define double @select_fcmp_nnan_nsz_ole_zero_unary_fneg(double %x) { 628; CHECK-LABEL: @select_fcmp_nnan_nsz_ole_zero_unary_fneg( 629; CHECK-NEXT: [[LEZERO:%.*]] = fcmp ole double [[X:%.*]], 0.000000e+00 630; CHECK-NEXT: [[NEGX:%.*]] = fneg fast double [[X]] 631; CHECK-NEXT: [[FABS:%.*]] = select i1 [[LEZERO]], double [[NEGX]], double [[X]] 632; CHECK-NEXT: ret double [[FABS]] 633; 634 %lezero = fcmp ole double %x, 0.0 635 %negx = fneg fast double %x 636 %fabs = select i1 %lezero, double %negx, double %x 637 ret double %fabs 638} 639 640; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically. 641 642define double @select_fcmp_nnan_nsz_ule_zero_unary_fneg(double %x) { 643; CHECK-LABEL: @select_fcmp_nnan_nsz_ule_zero_unary_fneg( 644; CHECK-NEXT: [[LEZERO:%.*]] = fcmp ule double [[X:%.*]], 0.000000e+00 645; CHECK-NEXT: [[NEGX:%.*]] = fneg fast double [[X]] 646; CHECK-NEXT: [[FABS:%.*]] = select i1 [[LEZERO]], double [[NEGX]], double [[X]] 647; CHECK-NEXT: ret double [[FABS]] 648; 649 %lezero = fcmp ule double %x, 0.0 650 %negx = fneg fast double %x 651 %fabs = select i1 %lezero, double %negx, double %x 652 ret double %fabs 653} 654 655; X <= -0.0 ? -X : X --> fabs(X) 656 657define float @select_fcmp_nnan_nsz_ole_negzero(float %x) { 658; CHECK-LABEL: @select_fcmp_nnan_nsz_ole_negzero( 659; CHECK-NEXT: [[LEZERO:%.*]] = fcmp ole float [[X:%.*]], 0.000000e+00 660; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan nsz float [[X]] 661; CHECK-NEXT: [[FABS:%.*]] = select i1 [[LEZERO]], float [[NEGX]], float [[X]] 662; CHECK-NEXT: ret float [[FABS]] 663; 664 %lezero = fcmp ole float %x, -0.0 665 %negx = fsub nnan nsz float -0.0, %x 666 %fabs = select i1 %lezero, float %negx, float %x 667 ret float %fabs 668} 669 670define float @select_nnan_nsz_fcmp_nnan_nsz_ole_negzero(float %x) { 671; CHECK-LABEL: @select_nnan_nsz_fcmp_nnan_nsz_ole_negzero( 672; CHECK-NEXT: [[TMP1:%.*]] = call nnan nsz float @llvm.fabs.f32(float [[X:%.*]]) 673; CHECK-NEXT: ret float [[TMP1]] 674; 675 %lezero = fcmp ole float %x, -0.0 676 %negx = fsub nnan nsz float -0.0, %x 677 %fabs = select nnan nsz i1 %lezero, float %negx, float %x 678 ret float %fabs 679} 680 681; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically. 682 683define float @select_fcmp_nnan_nsz_ule_negzero(float %x) { 684; CHECK-LABEL: @select_fcmp_nnan_nsz_ule_negzero( 685; CHECK-NEXT: [[LEZERO:%.*]] = fcmp ule float [[X:%.*]], 0.000000e+00 686; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan nsz float [[X]] 687; CHECK-NEXT: [[FABS:%.*]] = select i1 [[LEZERO]], float [[NEGX]], float [[X]] 688; CHECK-NEXT: ret float [[FABS]] 689; 690 %lezero = fcmp ule float %x, -0.0 691 %negx = fsub nnan nsz float -0.0, %x 692 %fabs = select i1 %lezero, float %negx, float %x 693 ret float %fabs 694} 695 696define float @select_fcmp_nnan_nsz_ole_negzero_unary_fneg(float %x) { 697; CHECK-LABEL: @select_fcmp_nnan_nsz_ole_negzero_unary_fneg( 698; CHECK-NEXT: [[LEZERO:%.*]] = fcmp ole float [[X:%.*]], 0.000000e+00 699; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan nsz float [[X]] 700; CHECK-NEXT: [[FABS:%.*]] = select i1 [[LEZERO]], float [[NEGX]], float [[X]] 701; CHECK-NEXT: ret float [[FABS]] 702; 703 %lezero = fcmp ole float %x, -0.0 704 %negx = fneg nnan nsz float %x 705 %fabs = select i1 %lezero, float %negx, float %x 706 ret float %fabs 707} 708 709; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically. 710 711define float @select_fcmp_nnan_nsz_ule_negzero_unary_fneg(float %x) { 712; CHECK-LABEL: @select_fcmp_nnan_nsz_ule_negzero_unary_fneg( 713; CHECK-NEXT: [[LEZERO:%.*]] = fcmp ule float [[X:%.*]], 0.000000e+00 714; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan nsz float [[X]] 715; CHECK-NEXT: [[FABS:%.*]] = select i1 [[LEZERO]], float [[NEGX]], float [[X]] 716; CHECK-NEXT: ret float [[FABS]] 717; 718 %lezero = fcmp ule float %x, -0.0 719 %negx = fneg nnan nsz float %x 720 %fabs = select i1 %lezero, float %negx, float %x 721 ret float %fabs 722} 723 724; X > 0.0 ? X : (0.0 - X) --> fabs(X) 725 726define <2 x float> @select_fcmp_ogt_zero_unary_fneg(<2 x float> %x) { 727; CHECK-LABEL: @select_fcmp_ogt_zero_unary_fneg( 728; CHECK-NEXT: [[TMP1:%.*]] = call nsz <2 x float> @llvm.fabs.v2f32(<2 x float> [[X:%.*]]) 729; CHECK-NEXT: ret <2 x float> [[TMP1]] 730; 731 %gtzero = fcmp ogt <2 x float> %x, zeroinitializer 732 %negx = fneg <2 x float> %x 733 %fabs = select nsz <2 x i1> %gtzero, <2 x float> %x, <2 x float> %negx 734 ret <2 x float> %fabs 735} 736 737define <2 x float> @select_fcmp_nnan_nsz_ogt_zero(<2 x float> %x) { 738; CHECK-LABEL: @select_fcmp_nnan_nsz_ogt_zero( 739; CHECK-NEXT: [[GTZERO:%.*]] = fcmp ogt <2 x float> [[X:%.*]], zeroinitializer 740; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan nsz arcp <2 x float> [[X]] 741; CHECK-NEXT: [[FABS:%.*]] = select <2 x i1> [[GTZERO]], <2 x float> [[X]], <2 x float> [[NEGX]] 742; CHECK-NEXT: ret <2 x float> [[FABS]] 743; 744 %gtzero = fcmp ogt <2 x float> %x, zeroinitializer 745 %negx = fsub nnan nsz arcp <2 x float> <float -0.0, float -0.0>, %x 746 %fabs = select <2 x i1> %gtzero, <2 x float> %x, <2 x float> %negx 747 ret <2 x float> %fabs 748} 749 750; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically. 751 752define <2 x float> @select_fcmp_nnan_nsz_ugt_zero(<2 x float> %x) { 753; CHECK-LABEL: @select_fcmp_nnan_nsz_ugt_zero( 754; CHECK-NEXT: [[GTZERO:%.*]] = fcmp ugt <2 x float> [[X:%.*]], zeroinitializer 755; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan nsz arcp <2 x float> [[X]] 756; CHECK-NEXT: [[FABS:%.*]] = select <2 x i1> [[GTZERO]], <2 x float> [[X]], <2 x float> [[NEGX]] 757; CHECK-NEXT: ret <2 x float> [[FABS]] 758; 759 %gtzero = fcmp ugt <2 x float> %x, zeroinitializer 760 %negx = fsub nnan nsz arcp <2 x float> <float -0.0, float -0.0>, %x 761 %fabs = select <2 x i1> %gtzero, <2 x float> %x, <2 x float> %negx 762 ret <2 x float> %fabs 763} 764 765define <2 x float> @select_fcmp_nnan_nsz_ogt_zero_unary_fneg(<2 x float> %x) { 766; CHECK-LABEL: @select_fcmp_nnan_nsz_ogt_zero_unary_fneg( 767; CHECK-NEXT: [[GTZERO:%.*]] = fcmp ogt <2 x float> [[X:%.*]], zeroinitializer 768; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan nsz arcp <2 x float> [[X]] 769; CHECK-NEXT: [[FABS:%.*]] = select <2 x i1> [[GTZERO]], <2 x float> [[X]], <2 x float> [[NEGX]] 770; CHECK-NEXT: ret <2 x float> [[FABS]] 771; 772 %gtzero = fcmp ogt <2 x float> %x, zeroinitializer 773 %negx = fneg nnan nsz arcp <2 x float> %x 774 %fabs = select <2 x i1> %gtzero, <2 x float> %x, <2 x float> %negx 775 ret <2 x float> %fabs 776} 777 778; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically. 779 780define <2 x float> @select_fcmp_nnan_nsz_ugt_zero_unary_fneg(<2 x float> %x) { 781; CHECK-LABEL: @select_fcmp_nnan_nsz_ugt_zero_unary_fneg( 782; CHECK-NEXT: [[GTZERO:%.*]] = fcmp ugt <2 x float> [[X:%.*]], zeroinitializer 783; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan nsz arcp <2 x float> [[X]] 784; CHECK-NEXT: [[FABS:%.*]] = select <2 x i1> [[GTZERO]], <2 x float> [[X]], <2 x float> [[NEGX]] 785; CHECK-NEXT: ret <2 x float> [[FABS]] 786; 787 %gtzero = fcmp ugt <2 x float> %x, zeroinitializer 788 %negx = fneg nnan nsz arcp <2 x float> %x 789 %fabs = select <2 x i1> %gtzero, <2 x float> %x, <2 x float> %negx 790 ret <2 x float> %fabs 791} 792 793; X > -0.0 ? X : (0.0 - X) --> fabs(X) 794 795define half @select_fcmp_nnan_nsz_ogt_negzero(half %x) { 796; CHECK-LABEL: @select_fcmp_nnan_nsz_ogt_negzero( 797; CHECK-NEXT: [[GTZERO:%.*]] = fcmp ogt half [[X:%.*]], 0xH0000 798; CHECK-NEXT: [[NEGX:%.*]] = fneg fast half [[X]] 799; CHECK-NEXT: [[FABS:%.*]] = select i1 [[GTZERO]], half [[X]], half [[NEGX]] 800; CHECK-NEXT: ret half [[FABS]] 801; 802 %gtzero = fcmp ogt half %x, -0.0 803 %negx = fsub fast half 0.0, %x 804 %fabs = select i1 %gtzero, half %x, half %negx 805 ret half %fabs 806} 807 808; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically. 809 810define half @select_fcmp_nnan_nsz_ugt_negzero(half %x) { 811; CHECK-LABEL: @select_fcmp_nnan_nsz_ugt_negzero( 812; CHECK-NEXT: [[GTZERO:%.*]] = fcmp ugt half [[X:%.*]], 0xH0000 813; CHECK-NEXT: [[NEGX:%.*]] = fneg fast half [[X]] 814; CHECK-NEXT: [[FABS:%.*]] = select i1 [[GTZERO]], half [[X]], half [[NEGX]] 815; CHECK-NEXT: ret half [[FABS]] 816; 817 %gtzero = fcmp ugt half %x, -0.0 818 %negx = fsub fast half 0.0, %x 819 %fabs = select i1 %gtzero, half %x, half %negx 820 ret half %fabs 821} 822 823; X > 0.0 ? X : (0.0 - X) --> fabs(X) 824 825define <2 x double> @select_fcmp_nnan_nsz_oge_zero(<2 x double> %x) { 826; CHECK-LABEL: @select_fcmp_nnan_nsz_oge_zero( 827; CHECK-NEXT: [[GEZERO:%.*]] = fcmp oge <2 x double> [[X:%.*]], zeroinitializer 828; CHECK-NEXT: [[NEGX:%.*]] = fneg reassoc nnan nsz <2 x double> [[X]] 829; CHECK-NEXT: [[FABS:%.*]] = select <2 x i1> [[GEZERO]], <2 x double> [[X]], <2 x double> [[NEGX]] 830; CHECK-NEXT: ret <2 x double> [[FABS]] 831; 832 %gezero = fcmp oge <2 x double> %x, zeroinitializer 833 %negx = fsub nnan nsz reassoc <2 x double> <double -0.0, double -0.0>, %x 834 %fabs = select <2 x i1> %gezero, <2 x double> %x, <2 x double> %negx 835 ret <2 x double> %fabs 836} 837 838; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically. 839 840define <2 x double> @select_fcmp_nnan_nsz_uge_zero(<2 x double> %x) { 841; CHECK-LABEL: @select_fcmp_nnan_nsz_uge_zero( 842; CHECK-NEXT: [[GEZERO:%.*]] = fcmp uge <2 x double> [[X:%.*]], zeroinitializer 843; CHECK-NEXT: [[NEGX:%.*]] = fneg reassoc nnan nsz <2 x double> [[X]] 844; CHECK-NEXT: [[FABS:%.*]] = select <2 x i1> [[GEZERO]], <2 x double> [[X]], <2 x double> [[NEGX]] 845; CHECK-NEXT: ret <2 x double> [[FABS]] 846; 847 %gezero = fcmp uge <2 x double> %x, zeroinitializer 848 %negx = fsub nnan nsz reassoc <2 x double> <double -0.0, double -0.0>, %x 849 %fabs = select <2 x i1> %gezero, <2 x double> %x, <2 x double> %negx 850 ret <2 x double> %fabs 851} 852 853define <2 x double> @select_fcmp_nnan_nsz_oge_zero_unary_fneg(<2 x double> %x) { 854; CHECK-LABEL: @select_fcmp_nnan_nsz_oge_zero_unary_fneg( 855; CHECK-NEXT: [[GEZERO:%.*]] = fcmp oge <2 x double> [[X:%.*]], zeroinitializer 856; CHECK-NEXT: [[NEGX:%.*]] = fneg reassoc nnan nsz <2 x double> [[X]] 857; CHECK-NEXT: [[FABS:%.*]] = select <2 x i1> [[GEZERO]], <2 x double> [[X]], <2 x double> [[NEGX]] 858; CHECK-NEXT: ret <2 x double> [[FABS]] 859; 860 %gezero = fcmp oge <2 x double> %x, zeroinitializer 861 %negx = fneg nnan nsz reassoc <2 x double> %x 862 %fabs = select <2 x i1> %gezero, <2 x double> %x, <2 x double> %negx 863 ret <2 x double> %fabs 864} 865 866; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically. 867 868define <2 x double> @select_fcmp_nnan_nsz_uge_zero_unary_fneg(<2 x double> %x) { 869; CHECK-LABEL: @select_fcmp_nnan_nsz_uge_zero_unary_fneg( 870; CHECK-NEXT: [[GEZERO:%.*]] = fcmp uge <2 x double> [[X:%.*]], zeroinitializer 871; CHECK-NEXT: [[NEGX:%.*]] = fneg reassoc nnan nsz <2 x double> [[X]] 872; CHECK-NEXT: [[FABS:%.*]] = select <2 x i1> [[GEZERO]], <2 x double> [[X]], <2 x double> [[NEGX]] 873; CHECK-NEXT: ret <2 x double> [[FABS]] 874; 875 %gezero = fcmp uge <2 x double> %x, zeroinitializer 876 %negx = fneg nnan nsz reassoc <2 x double> %x 877 %fabs = select <2 x i1> %gezero, <2 x double> %x, <2 x double> %negx 878 ret <2 x double> %fabs 879} 880 881; X > -0.0 ? X : (0.0 - X) --> fabs(X) 882 883define half @select_fcmp_nnan_nsz_oge_negzero(half %x) { 884; CHECK-LABEL: @select_fcmp_nnan_nsz_oge_negzero( 885; CHECK-NEXT: [[GEZERO:%.*]] = fcmp oge half [[X:%.*]], 0xH0000 886; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan nsz half [[X]] 887; CHECK-NEXT: [[FABS:%.*]] = select i1 [[GEZERO]], half [[X]], half [[NEGX]] 888; CHECK-NEXT: ret half [[FABS]] 889; 890 %gezero = fcmp oge half %x, -0.0 891 %negx = fsub nnan nsz half -0.0, %x 892 %fabs = select i1 %gezero, half %x, half %negx 893 ret half %fabs 894} 895 896; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically. 897 898define half @select_fcmp_nnan_nsz_uge_negzero(half %x) { 899; CHECK-LABEL: @select_fcmp_nnan_nsz_uge_negzero( 900; CHECK-NEXT: [[GEZERO:%.*]] = fcmp uge half [[X:%.*]], 0xH0000 901; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan nsz half [[X]] 902; CHECK-NEXT: [[FABS:%.*]] = select i1 [[GEZERO]], half [[X]], half [[NEGX]] 903; CHECK-NEXT: ret half [[FABS]] 904; 905 %gezero = fcmp uge half %x, -0.0 906 %negx = fsub nnan nsz half -0.0, %x 907 %fabs = select i1 %gezero, half %x, half %negx 908 ret half %fabs 909} 910 911define half @select_fcmp_nnan_nsz_oge_negzero_unary_fneg(half %x) { 912; CHECK-LABEL: @select_fcmp_nnan_nsz_oge_negzero_unary_fneg( 913; CHECK-NEXT: [[GEZERO:%.*]] = fcmp oge half [[X:%.*]], 0xH0000 914; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan nsz half [[X]] 915; CHECK-NEXT: [[FABS:%.*]] = select i1 [[GEZERO]], half [[X]], half [[NEGX]] 916; CHECK-NEXT: ret half [[FABS]] 917; 918 %gezero = fcmp oge half %x, -0.0 919 %negx = fneg nnan nsz half %x 920 %fabs = select i1 %gezero, half %x, half %negx 921 ret half %fabs 922} 923 924; Repeat with unordered predicate - nnan allows us to treat ordered/unordered identically. 925 926define half @select_fcmp_nnan_nsz_uge_negzero_unary_fneg(half %x) { 927; CHECK-LABEL: @select_fcmp_nnan_nsz_uge_negzero_unary_fneg( 928; CHECK-NEXT: [[GEZERO:%.*]] = fcmp uge half [[X:%.*]], 0xH0000 929; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan nsz half [[X]] 930; CHECK-NEXT: [[FABS:%.*]] = select i1 [[GEZERO]], half [[X]], half [[NEGX]] 931; CHECK-NEXT: ret half [[FABS]] 932; 933 %gezero = fcmp uge half %x, -0.0 934 %negx = fneg nnan nsz half %x 935 %fabs = select i1 %gezero, half %x, half %negx 936 ret half %fabs 937} 938 939define float @select_fneg(i1 %c, float %x) { 940; CHECK-LABEL: @select_fneg( 941; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]]) 942; CHECK-NEXT: ret float [[FABS]] 943; 944 %n = fneg float %x 945 %s = select i1 %c, float %n, float %x 946 %fabs = call float @llvm.fabs.f32(float %s) 947 ret float %fabs 948} 949 950define float @select_fneg_use1(i1 %c, float %x) { 951; CHECK-LABEL: @select_fneg_use1( 952; CHECK-NEXT: [[N:%.*]] = fneg float [[X:%.*]] 953; CHECK-NEXT: call void @use(float [[N]]) 954; CHECK-NEXT: [[FABS:%.*]] = call fast float @llvm.fabs.f32(float [[X]]) 955; CHECK-NEXT: ret float [[FABS]] 956; 957 %n = fneg float %x 958 call void @use(float %n) 959 %s = select i1 %c, float %x, float %n 960 %fabs = call fast float @llvm.fabs.f32(float %s) 961 ret float %fabs 962} 963 964define float @select_fneg_use2(i1 %c, float %x) { 965; CHECK-LABEL: @select_fneg_use2( 966; CHECK-NEXT: [[N:%.*]] = fneg arcp float [[X:%.*]] 967; CHECK-NEXT: [[S:%.*]] = select i1 [[C:%.*]], float [[N]], float [[X]] 968; CHECK-NEXT: call void @use(float [[S]]) 969; CHECK-NEXT: [[FABS:%.*]] = call nnan nsz float @llvm.fabs.f32(float [[X]]) 970; CHECK-NEXT: ret float [[FABS]] 971; 972 %n = fneg arcp float %x 973 %s = select i1 %c, float %n, float %x 974 call void @use(float %s) 975 %fabs = call nnan nsz float @llvm.fabs.f32(float %s) 976 ret float %fabs 977} 978 979define <2 x float> @select_fneg_vec(<2 x i1> %c, <2 x float> %x) { 980; CHECK-LABEL: @select_fneg_vec( 981; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[X:%.*]]) 982; CHECK-NEXT: ret <2 x float> [[FABS]] 983; 984 %n = fneg <2 x float> %x 985 %s = select fast <2 x i1> %c, <2 x float> %x, <2 x float> %n 986 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %s) 987 ret <2 x float> %fabs 988} 989