1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -instsimplify -S | FileCheck %s 3 4; fneg (fneg X) ==> X 5define float @fneg_fneg_var(float %a) { 6; CHECK-LABEL: @fneg_fneg_var( 7; CHECK-NEXT: ret float [[A:%.*]] 8; 9 %r = fneg float %a 10 %r1 = fneg float %r 11 ret float %r1 12} 13 14; fneg (fsub -0.0, X) ==> X 15define float @fsub_-0_x(float %a) { 16; CHECK-LABEL: @fsub_-0_x( 17; CHECK-NEXT: ret float [[A:%.*]] 18; 19 %t1 = fsub float -0.0, %a 20 %ret = fneg float %t1 21 ret float %ret 22} 23 24define <2 x float> @fsub_-0_x_vec(<2 x float> %a) { 25; CHECK-LABEL: @fsub_-0_x_vec( 26; CHECK-NEXT: ret <2 x float> [[A:%.*]] 27; 28 %t1 = fsub <2 x float> <float -0.0, float -0.0>, %a 29 %ret = fneg <2 x float> %t1 30 ret <2 x float> %ret 31} 32 33define <2 x float> @fsub_-0_x_vec_undef_elts(<2 x float> %a) { 34; CHECK-LABEL: @fsub_-0_x_vec_undef_elts( 35; CHECK-NEXT: ret <2 x float> [[A:%.*]] 36; 37 %t1 = fsub <2 x float> <float -0.0, float undef>, %a 38 %ret = fneg <2 x float> %t1 39 ret <2 x float> %ret 40} 41 42define <2 x float> @fsub_negzero_vec_undef_elts(<2 x float> %x) { 43; CHECK-LABEL: @fsub_negzero_vec_undef_elts( 44; CHECK-NEXT: ret <2 x float> [[X:%.*]] 45; 46 %r = fsub nsz <2 x float> %x, <float undef, float -0.0> 47 ret <2 x float> %r 48} 49 50; fsub -0.0, (fsub -0.0, X) ==> X 51define float @fsub_-0_-0_x(float %a) { 52; CHECK-LABEL: @fsub_-0_-0_x( 53; CHECK-NEXT: ret float [[A:%.*]] 54; 55 %t1 = fsub float -0.0, %a 56 %ret = fsub float -0.0, %t1 57 ret float %ret 58} 59 60; fsub -0.0, (fneg X) ==> X 61define float @fneg_x(float %a) { 62; CHECK-LABEL: @fneg_x( 63; CHECK-NEXT: ret float [[A:%.*]] 64; 65 %t1 = fneg float %a 66 %ret = fsub float -0.0, %t1 67 ret float %ret 68} 69 70define <2 x float> @fsub_-0_-0_x_vec(<2 x float> %a) { 71; CHECK-LABEL: @fsub_-0_-0_x_vec( 72; CHECK-NEXT: ret <2 x float> [[A:%.*]] 73; 74 %t1 = fsub <2 x float> <float -0.0, float -0.0>, %a 75 %ret = fsub <2 x float> <float -0.0, float -0.0>, %t1 76 ret <2 x float> %ret 77} 78 79define <2 x float> @fneg_x_vec(<2 x float> %a) { 80; CHECK-LABEL: @fneg_x_vec( 81; CHECK-NEXT: ret <2 x float> [[A:%.*]] 82; 83 %t1 = fneg <2 x float> %a 84 %ret = fsub <2 x float> <float -0.0, float -0.0>, %t1 85 ret <2 x float> %ret 86} 87 88define <2 x float> @fsub_-0_-0_x_vec_undef_elts(<2 x float> %a) { 89; CHECK-LABEL: @fsub_-0_-0_x_vec_undef_elts( 90; CHECK-NEXT: ret <2 x float> [[A:%.*]] 91; 92 %t1 = fsub <2 x float> <float undef, float -0.0>, %a 93 %ret = fsub <2 x float> <float -0.0, float undef>, %t1 94 ret <2 x float> %ret 95} 96 97define <2 x float> @fneg_x_vec_undef_elts(<2 x float> %a) { 98; CHECK-LABEL: @fneg_x_vec_undef_elts( 99; CHECK-NEXT: ret <2 x float> [[A:%.*]] 100; 101 %t1 = fneg <2 x float> %a 102 %ret = fsub <2 x float> <float -0.0, float undef>, %t1 103 ret <2 x float> %ret 104} 105 106; fsub -0.0, (fsub 0.0, X) != X 107define float @fsub_-0_0_x(float %a) { 108; CHECK-LABEL: @fsub_-0_0_x( 109; CHECK-NEXT: [[T1:%.*]] = fsub float 0.000000e+00, [[A:%.*]] 110; CHECK-NEXT: [[RET:%.*]] = fsub float -0.000000e+00, [[T1]] 111; CHECK-NEXT: ret float [[RET]] 112; 113 %t1 = fsub float 0.0, %a 114 %ret = fsub float -0.0, %t1 115 ret float %ret 116} 117 118; fsub 0.0, (fsub -0.0, X) != X 119define float @fsub_0_-0_x(float %a) { 120; CHECK-LABEL: @fsub_0_-0_x( 121; CHECK-NEXT: [[T1:%.*]] = fsub float -0.000000e+00, [[A:%.*]] 122; CHECK-NEXT: [[RET:%.*]] = fsub float 0.000000e+00, [[T1]] 123; CHECK-NEXT: ret float [[RET]] 124; 125 %t1 = fsub float -0.0, %a 126 %ret = fsub float 0.0, %t1 127 ret float %ret 128} 129 130; fsub X, 0 ==> X 131define float @fsub_x_0(float %x) { 132; CHECK-LABEL: @fsub_x_0( 133; CHECK-NEXT: ret float [[X:%.*]] 134; 135 %r = fsub float %x, 0.0 136 ret float %r 137} 138 139define <2 x float> @fsub_x_0_vec_undef(<2 x float> %x) { 140; CHECK-LABEL: @fsub_x_0_vec_undef( 141; CHECK-NEXT: ret <2 x float> [[X:%.*]] 142; 143 %r = fsub <2 x float> %x, <float undef, float 0.0> 144 ret <2 x float> %r 145} 146 147; fadd X, -0 ==> X 148define float @fadd_x_n0(float %a) { 149; CHECK-LABEL: @fadd_x_n0( 150; CHECK-NEXT: ret float [[A:%.*]] 151; 152 %ret = fadd float %a, -0.0 153 ret float %ret 154} 155 156define <2 x float> @fadd_x_n0_vec_undef_elt(<2 x float> %a) { 157; CHECK-LABEL: @fadd_x_n0_vec_undef_elt( 158; CHECK-NEXT: ret <2 x float> [[A:%.*]] 159; 160 %ret = fadd <2 x float> %a, <float -0.0, float undef> 161 ret <2 x float> %ret 162} 163 164; fmul X, 1.0 ==> X 165define double @fmul_X_1(double %a) { 166; CHECK-LABEL: @fmul_X_1( 167; CHECK-NEXT: ret double [[A:%.*]] 168; 169 %b = fmul double 1.0, %a 170 ret double %b 171} 172 173; PR2642 174define <4 x float> @fmul_X_1_vec(<4 x float> %x) { 175; CHECK-LABEL: @fmul_X_1_vec( 176; CHECK-NEXT: ret <4 x float> [[X:%.*]] 177; 178 %m = fmul <4 x float> %x, <float 1.0, float 1.0, float 1.0, float 1.0> 179 ret <4 x float> %m 180} 181 182; fdiv X, 1.0 ==> X 183define float @fdiv_x_1(float %a) { 184; CHECK-LABEL: @fdiv_x_1( 185; CHECK-NEXT: ret float [[A:%.*]] 186; 187 %ret = fdiv float %a, 1.0 188 ret float %ret 189} 190 191; We can't optimize away the fadd in this test because the input 192; value to the function and subsequently to the fadd may be -0.0. 193; In that one special case, the result of the fadd should be +0.0 194; rather than the first parameter of the fadd. 195 196; Fragile test warning: We need 6 sqrt calls to trigger the bug 197; because the internal logic has a magic recursion limit of 6. 198; This is presented without any explanation or ability to customize. 199 200declare float @sqrtf(float) 201 202define float @PR22688(float %x) { 203; CHECK-LABEL: @PR22688( 204; CHECK-NEXT: [[TMP1:%.*]] = call float @sqrtf(float [[X:%.*]]) 205; CHECK-NEXT: [[TMP2:%.*]] = call float @sqrtf(float [[TMP1]]) 206; CHECK-NEXT: [[TMP3:%.*]] = call float @sqrtf(float [[TMP2]]) 207; CHECK-NEXT: [[TMP4:%.*]] = call float @sqrtf(float [[TMP3]]) 208; CHECK-NEXT: [[TMP5:%.*]] = call float @sqrtf(float [[TMP4]]) 209; CHECK-NEXT: [[TMP6:%.*]] = call float @sqrtf(float [[TMP5]]) 210; CHECK-NEXT: [[TMP7:%.*]] = fadd float [[TMP6]], 0.000000e+00 211; CHECK-NEXT: ret float [[TMP7]] 212; 213 %1 = call float @sqrtf(float %x) 214 %2 = call float @sqrtf(float %1) 215 %3 = call float @sqrtf(float %2) 216 %4 = call float @sqrtf(float %3) 217 %5 = call float @sqrtf(float %4) 218 %6 = call float @sqrtf(float %5) 219 %7 = fadd float %6, 0.0 220 ret float %7 221} 222 223declare float @llvm.fabs.f32(float) 224declare <2 x float> @llvm.fabs.v2f32(<2 x float>) 225declare float @llvm.sqrt.f32(float) 226declare float @llvm.maxnum.f32(float, float) 227 228define float @fabs_select_positive_constants(i32 %c) { 229; CHECK-LABEL: @fabs_select_positive_constants( 230; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 231; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 1.000000e+00, float 2.000000e+00 232; CHECK-NEXT: ret float [[SELECT]] 233; 234 %cmp = icmp eq i32 %c, 0 235 %select = select i1 %cmp, float 1.0, float 2.0 236 %fabs = call float @llvm.fabs.f32(float %select) 237 ret float %fabs 238} 239 240define <2 x float> @fabs_select_positive_constants_vector(i32 %c) { 241; CHECK-LABEL: @fabs_select_positive_constants_vector( 242; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 243; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 1.000000e+00, float 1.000000e+00>, <2 x float> <float 2.000000e+00, float 2.000000e+00> 244; CHECK-NEXT: ret <2 x float> [[SELECT]] 245; 246 %cmp = icmp eq i32 %c, 0 247 %select = select i1 %cmp, <2 x float> <float 1.0, float 1.0>, <2 x float> <float 2.0, float 2.0> 248 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 249 ret <2 x float> %fabs 250} 251 252define float @fabs_select_constant_variable(i32 %c, float %x) { 253; CHECK-LABEL: @fabs_select_constant_variable( 254; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 255; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 1.000000e+00, float [[X:%.*]] 256; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) 257; CHECK-NEXT: ret float [[FABS]] 258; 259 %cmp = icmp eq i32 %c, 0 260 %select = select i1 %cmp, float 1.0, float %x 261 %fabs = call float @llvm.fabs.f32(float %select) 262 ret float %fabs 263} 264 265define <2 x float> @fabs_select_constant_variable_vector(i32 %c, <2 x float> %x) { 266; CHECK-LABEL: @fabs_select_constant_variable_vector( 267; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 268; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 1.000000e+00, float 1.000000e+00>, <2 x float> [[X:%.*]] 269; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]]) 270; CHECK-NEXT: ret <2 x float> [[FABS]] 271; 272 %cmp = icmp eq i32 %c, 0 273 %select = select i1 %cmp, <2 x float> <float 1.0, float 1.0>, <2 x float> %x 274 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 275 ret <2 x float> %fabs 276} 277 278define float @fabs_select_neg0_pos0(i32 %c) { 279; CHECK-LABEL: @fabs_select_neg0_pos0( 280; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 281; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float -0.000000e+00, float 0.000000e+00 282; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) 283; CHECK-NEXT: ret float [[FABS]] 284; 285 %cmp = icmp eq i32 %c, 0 286 %select = select i1 %cmp, float -0.0, float 0.0 287 %fabs = call float @llvm.fabs.f32(float %select) 288 ret float %fabs 289} 290 291define <2 x float> @fabs_select_neg0_pos0_vector(i32 %c) { 292; CHECK-LABEL: @fabs_select_neg0_pos0_vector( 293; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 294; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float -0.000000e+00, float -0.000000e+00>, <2 x float> zeroinitializer 295; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]]) 296; CHECK-NEXT: ret <2 x float> [[FABS]] 297; 298 %cmp = icmp eq i32 %c, 0 299 %select = select i1 %cmp, <2 x float> <float -0.0, float -0.0>, <2 x float> <float 0.0, float 0.0> 300 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 301 ret <2 x float> %fabs 302} 303 304define float @fabs_select_neg0_neg1(i32 %c) { 305; CHECK-LABEL: @fabs_select_neg0_neg1( 306; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 307; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float -0.000000e+00, float -1.000000e+00 308; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) 309; CHECK-NEXT: ret float [[FABS]] 310; 311 %cmp = icmp eq i32 %c, 0 312 %select = select i1 %cmp, float -0.0, float -1.0 313 %fabs = call float @llvm.fabs.f32(float %select) 314 ret float %fabs 315} 316 317define <2 x float> @fabs_select_neg0_neg1_vector(i32 %c) { 318; CHECK-LABEL: @fabs_select_neg0_neg1_vector( 319; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 320; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float -0.000000e+00, float -0.000000e+00>, <2 x float> <float -1.000000e+00, float -1.000000e+00> 321; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]]) 322; CHECK-NEXT: ret <2 x float> [[FABS]] 323; 324 %cmp = icmp eq i32 %c, 0 325 %select = select i1 %cmp, <2 x float> <float -0.0, float -0.0>, <2 x float> <float -1.0, float -1.0> 326 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 327 ret <2 x float> %fabs 328} 329 330define float @fabs_select_nan_nan(i32 %c) { 331; CHECK-LABEL: @fabs_select_nan_nan( 332; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 333; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 0x7FF8000000000000, float 0x7FF8000100000000 334; CHECK-NEXT: ret float [[SELECT]] 335; 336 %cmp = icmp eq i32 %c, 0 337 %select = select i1 %cmp, float 0x7FF8000000000000, float 0x7FF8000100000000 338 %fabs = call float @llvm.fabs.f32(float %select) 339 ret float %fabs 340} 341 342define <2 x float> @fabs_select_nan_nan_vector(i32 %c) { 343; CHECK-LABEL: @fabs_select_nan_nan_vector( 344; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 345; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000> 346; CHECK-NEXT: ret <2 x float> [[SELECT]] 347; 348 %cmp = icmp eq i32 %c, 0 349 %select = select i1 %cmp, <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000> 350 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 351 ret <2 x float> %fabs 352} 353 354define float @fabs_select_negnan_nan(i32 %c) { 355; CHECK-LABEL: @fabs_select_negnan_nan( 356; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 357; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float 0x7FF8000000000000 358; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) 359; CHECK-NEXT: ret float [[FABS]] 360; 361 %cmp = icmp eq i32 %c, 0 362 %select = select i1 %cmp, float 0xFFF8000000000000, float 0x7FF8000000000000 363 %fabs = call float @llvm.fabs.f32(float %select) 364 ret float %fabs 365} 366 367define <2 x float> @fabs_select_negnan_nan_vector(i32 %c) { 368; CHECK-LABEL: @fabs_select_negnan_nan_vector( 369; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 370; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000> 371; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]]) 372; CHECK-NEXT: ret <2 x float> [[FABS]] 373; 374 %cmp = icmp eq i32 %c, 0 375 %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000> 376 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 377 ret <2 x float> %fabs 378} 379 380define float @fabs_select_negnan_negnan(i32 %c) { 381; CHECK-LABEL: @fabs_select_negnan_negnan( 382; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 383; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float 0x7FF8000100000000 384; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) 385; CHECK-NEXT: ret float [[FABS]] 386; 387 %cmp = icmp eq i32 %c, 0 388 %select = select i1 %cmp, float 0xFFF8000000000000, float 0x7FF8000100000000 389 %fabs = call float @llvm.fabs.f32(float %select) 390 ret float %fabs 391} 392 393define <2 x float> @fabs_select_negnan_negnan_vector(i32 %c) { 394; CHECK-LABEL: @fabs_select_negnan_negnan_vector( 395; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 396; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000> 397; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]]) 398; CHECK-NEXT: ret <2 x float> [[FABS]] 399; 400 %cmp = icmp eq i32 %c, 0 401 %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000> 402 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 403 ret <2 x float> %fabs 404} 405 406define float @fabs_select_negnan_negzero(i32 %c) { 407; CHECK-LABEL: @fabs_select_negnan_negzero( 408; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 409; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float -0.000000e+00 410; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) 411; CHECK-NEXT: ret float [[FABS]] 412; 413 %cmp = icmp eq i32 %c, 0 414 %select = select i1 %cmp, float 0xFFF8000000000000, float -0.0 415 %fabs = call float @llvm.fabs.f32(float %select) 416 ret float %fabs 417} 418 419define <2 x float> @fabs_select_negnan_negzero_vector(i32 %c) { 420; CHECK-LABEL: @fabs_select_negnan_negzero_vector( 421; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 422; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float -0.000000e+00, float -0.000000e+00> 423; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]]) 424; CHECK-NEXT: ret <2 x float> [[FABS]] 425; 426 %cmp = icmp eq i32 %c, 0 427 %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float -0.0, float -0.0> 428 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 429 ret <2 x float> %fabs 430} 431 432define float @fabs_select_negnan_zero(i32 %c) { 433; CHECK-LABEL: @fabs_select_negnan_zero( 434; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 435; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float 0.000000e+00 436; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) 437; CHECK-NEXT: ret float [[FABS]] 438; 439 %cmp = icmp eq i32 %c, 0 440 %select = select i1 %cmp, float 0xFFF8000000000000, float 0.0 441 %fabs = call float @llvm.fabs.f32(float %select) 442 ret float %fabs 443} 444 445define <2 x float> @fabs_select_negnan_zero_vector(i32 %c) { 446; CHECK-LABEL: @fabs_select_negnan_zero_vector( 447; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 448; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> zeroinitializer 449; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]]) 450; CHECK-NEXT: ret <2 x float> [[FABS]] 451; 452 %cmp = icmp eq i32 %c, 0 453 %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0.0, float 0.0> 454 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 455 ret <2 x float> %fabs 456} 457 458; The fabs can't be eliminated because llvm.sqrt.f32 may return -0 or NaN with 459; an arbitrary sign bit. 460define float @fabs_sqrt(float %a) { 461; CHECK-LABEL: @fabs_sqrt( 462; CHECK-NEXT: [[SQRT:%.*]] = call float @llvm.sqrt.f32(float [[A:%.*]]) 463; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]]) 464; CHECK-NEXT: ret float [[FABS]] 465; 466 %sqrt = call float @llvm.sqrt.f32(float %a) 467 %fabs = call float @llvm.fabs.f32(float %sqrt) 468 ret float %fabs 469} 470 471; The fabs can't be eliminated because the nnan sqrt may still return -0. 472define float @fabs_sqrt_nnan(float %a) { 473; CHECK-LABEL: @fabs_sqrt_nnan( 474; CHECK-NEXT: [[SQRT:%.*]] = call nnan float @llvm.sqrt.f32(float [[A:%.*]]) 475; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]]) 476; CHECK-NEXT: ret float [[FABS]] 477; 478 %sqrt = call nnan float @llvm.sqrt.f32(float %a) 479 %fabs = call float @llvm.fabs.f32(float %sqrt) 480 ret float %fabs 481} 482 483; The fabs can't be eliminated because the nsz sqrt may still return NaN. 484define float @fabs_sqrt_nsz(float %a) { 485; CHECK-LABEL: @fabs_sqrt_nsz( 486; CHECK-NEXT: [[SQRT:%.*]] = call nsz float @llvm.sqrt.f32(float [[A:%.*]]) 487; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]]) 488; CHECK-NEXT: ret float [[FABS]] 489; 490 %sqrt = call nsz float @llvm.sqrt.f32(float %a) 491 %fabs = call float @llvm.fabs.f32(float %sqrt) 492 ret float %fabs 493} 494 495; The fabs can be eliminated because we're nsz and nnan. 496define float @fabs_sqrt_nnan_nsz(float %a) { 497; CHECK-LABEL: @fabs_sqrt_nnan_nsz( 498; CHECK-NEXT: [[SQRT:%.*]] = call nnan nsz float @llvm.sqrt.f32(float [[A:%.*]]) 499; CHECK-NEXT: ret float [[SQRT]] 500; 501 %sqrt = call nnan nsz float @llvm.sqrt.f32(float %a) 502 %fabs = call float @llvm.fabs.f32(float %sqrt) 503 ret float %fabs 504} 505 506; The second fabs can be eliminated because the operand to sqrt cannot be -0. 507define float @fabs_sqrt_nnan_fabs(float %a) { 508; CHECK-LABEL: @fabs_sqrt_nnan_fabs( 509; CHECK-NEXT: [[B:%.*]] = call float @llvm.fabs.f32(float [[A:%.*]]) 510; CHECK-NEXT: [[SQRT:%.*]] = call nnan float @llvm.sqrt.f32(float [[B]]) 511; CHECK-NEXT: ret float [[SQRT]] 512; 513 %b = call float @llvm.fabs.f32(float %a) 514 %sqrt = call nnan float @llvm.sqrt.f32(float %b) 515 %fabs = call float @llvm.fabs.f32(float %sqrt) 516 ret float %fabs 517} 518 519define float @fabs_select_positive_constants_vector_extract(i32 %c) { 520; CHECK-LABEL: @fabs_select_positive_constants_vector_extract( 521; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 522; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 1.000000e+00, float 1.000000e+00>, <2 x float> <float 2.000000e+00, float 2.000000e+00> 523; CHECK-NEXT: [[EXTRACT:%.*]] = extractelement <2 x float> [[SELECT]], i32 0 524; CHECK-NEXT: ret float [[EXTRACT]] 525; 526 %cmp = icmp eq i32 %c, 0 527 %select = select i1 %cmp, <2 x float> <float 1.0, float 1.0>, <2 x float> <float 2.0, float 2.0> 528 %extract = extractelement <2 x float> %select, i32 0 529 %fabs = call float @llvm.fabs.f32(float %extract) 530 ret float %fabs 531} 532 533; Y - (Y - X) --> X 534 535define float @fsub_fsub_common_op(float %x, float %y) { 536; CHECK-LABEL: @fsub_fsub_common_op( 537; CHECK-NEXT: ret float [[X:%.*]] 538; 539 %s = fsub float %y, %x 540 %r = fsub reassoc nsz float %y, %s 541 ret float %r 542} 543 544define <2 x float> @fsub_fsub_common_op_vec(<2 x float> %x, <2 x float> %y) { 545; CHECK-LABEL: @fsub_fsub_common_op_vec( 546; CHECK-NEXT: ret <2 x float> [[X:%.*]] 547; 548 %s = fsub <2 x float> %y, %x 549 %r = fsub reassoc nsz <2 x float> %y, %s 550 ret <2 x float> %r 551} 552 553; Negative test - fsub is not commutative. 554; Y - (X - Y) --> (Y - X) + Y (canonicalized) 555 556define float @fsub_fsub_wrong_common_op(float %x, float %y) { 557; CHECK-LABEL: @fsub_fsub_wrong_common_op( 558; CHECK-NEXT: [[S:%.*]] = fsub float [[X:%.*]], [[Y:%.*]] 559; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz float [[Y]], [[S]] 560; CHECK-NEXT: ret float [[R]] 561; 562 %s = fsub float %x, %y 563 %r = fsub reassoc nsz float %y, %s 564 ret float %r 565} 566 567; Negative test - negated operand needed. 568; (Y - X) - Y --> -X 569 570define float @fsub_fsub_common_op_wrong_commute(float %x, float %y) { 571; CHECK-LABEL: @fsub_fsub_common_op_wrong_commute( 572; CHECK-NEXT: [[S:%.*]] = fsub float [[Y:%.*]], [[X:%.*]] 573; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz float [[S]], [[Y]] 574; CHECK-NEXT: ret float [[R]] 575; 576 %s = fsub float %y, %x 577 %r = fsub reassoc nsz float %s, %y 578 ret float %r 579} 580 581; Negative test - fsub is not commutative. 582; (X - Y) - Y --> ? 583 584define float @fsub_fsub_wrong_common_op_wrong_commute(float %x, float %y) { 585; CHECK-LABEL: @fsub_fsub_wrong_common_op_wrong_commute( 586; CHECK-NEXT: [[S:%.*]] = fsub float [[X:%.*]], [[Y:%.*]] 587; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz float [[S]], [[Y]] 588; CHECK-NEXT: ret float [[R]] 589; 590 %s = fsub float %x, %y 591 %r = fsub reassoc nsz float %s, %y 592 ret float %r 593} 594 595; (Y + X) - Y --> X 596 597define float @fadd_fsub_common_op(float %x, float %y) { 598; CHECK-LABEL: @fadd_fsub_common_op( 599; CHECK-NEXT: ret float [[X:%.*]] 600; 601 %a = fadd float %y, %x 602 %r = fsub reassoc nsz float %a, %y 603 ret float %r 604} 605 606; (X + Y) - Y --> X 607 608define <2 x float> @fadd_fsub_common_op_commute_vec(<2 x float> %x, <2 x float> %y) { 609; CHECK-LABEL: @fadd_fsub_common_op_commute_vec( 610; CHECK-NEXT: ret <2 x float> [[X:%.*]] 611; 612 %a = fadd <2 x float> %x, %y 613 %r = fsub reassoc nsz <2 x float> %a, %y 614 ret <2 x float> %r 615} 616 617; Negative test - negated operand needed. 618; Y - (Y + X) --> -X 619 620define float @fadd_fsub_common_op_wrong_commute(float %x, float %y) { 621; CHECK-LABEL: @fadd_fsub_common_op_wrong_commute( 622; CHECK-NEXT: [[A:%.*]] = fadd float [[Y:%.*]], [[X:%.*]] 623; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz float [[Y]], [[A]] 624; CHECK-NEXT: ret float [[R]] 625; 626 %a = fadd float %y, %x 627 %r = fsub reassoc nsz float %y, %a 628 ret float %r 629} 630 631; Negative test - negated operand needed. 632; Y - (X + Y) --> -X 633 634define float @fadd_fsub_common_op_wrong_commute_commute(float %x, float %y) { 635; CHECK-LABEL: @fadd_fsub_common_op_wrong_commute_commute( 636; CHECK-NEXT: [[A:%.*]] = fadd float [[X:%.*]], [[Y:%.*]] 637; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz float [[Y]], [[A]] 638; CHECK-NEXT: ret float [[R]] 639; 640 %a = fadd float %x, %y 641 %r = fsub reassoc nsz float %y, %a 642 ret float %r 643} 644 645; Y + (X - Y) --> X 646 647define <2 x float> @fsub_fadd_common_op_vec(<2 x float> %x, <2 x float> %y) { 648; CHECK-LABEL: @fsub_fadd_common_op_vec( 649; CHECK-NEXT: ret <2 x float> [[X:%.*]] 650; 651 %s = fsub <2 x float> %x, %y 652 %r = fadd reassoc nsz <2 x float> %y, %s 653 ret <2 x float> %r 654} 655 656; (X - Y) + Y --> X 657 658define float @fsub_fadd_common_op_commute(float %x, float %y) { 659; CHECK-LABEL: @fsub_fadd_common_op_commute( 660; CHECK-NEXT: ret float [[X:%.*]] 661; 662 %s = fsub float %x, %y 663 %r = fadd reassoc nsz float %s, %y 664 ret float %r 665} 666 667; Negative test. 668; Y + (Y - X) --> ? 669 670define float @fsub_fadd_common_op_wrong_commute(float %x, float %y) { 671; CHECK-LABEL: @fsub_fadd_common_op_wrong_commute( 672; CHECK-NEXT: [[S:%.*]] = fsub float [[Y:%.*]], [[X:%.*]] 673; CHECK-NEXT: [[R:%.*]] = fadd reassoc nsz float [[Y]], [[S]] 674; CHECK-NEXT: ret float [[R]] 675; 676 %s = fsub float %y, %x 677 %r = fadd reassoc nsz float %y, %s 678 ret float %r 679} 680 681; Negative test. 682; (Y - X) + Y --> ? 683 684define float @fsub_fadd_common_op_wrong_commute_commute(float %x, float %y) { 685; CHECK-LABEL: @fsub_fadd_common_op_wrong_commute_commute( 686; CHECK-NEXT: [[S:%.*]] = fsub float [[Y:%.*]], [[X:%.*]] 687; CHECK-NEXT: [[R:%.*]] = fadd reassoc nsz float [[S]], [[Y]] 688; CHECK-NEXT: ret float [[R]] 689; 690 %s = fsub float %y, %x 691 %r = fadd reassoc nsz float %s, %y 692 ret float %r 693} 694 695; PR46627 - https://bugs.llvm.org/show_bug.cgi?id=46627 696 697define float @maxnum_with_poszero_op(float %a) { 698; CHECK-LABEL: @maxnum_with_poszero_op( 699; CHECK-NEXT: [[MAX:%.*]] = call float @llvm.maxnum.f32(float [[A:%.*]], float 0.000000e+00) 700; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]]) 701; CHECK-NEXT: ret float [[FABS]] 702; 703 %max = call float @llvm.maxnum.f32(float %a, float 0.0) 704 %fabs = call float @llvm.fabs.f32(float %max) 705 ret float %fabs 706} 707 708define float @maxnum_with_poszero_op_commute(float %a) { 709; CHECK-LABEL: @maxnum_with_poszero_op_commute( 710; CHECK-NEXT: [[SQRT:%.*]] = call float @llvm.sqrt.f32(float [[A:%.*]]) 711; CHECK-NEXT: [[MAX:%.*]] = call float @llvm.maxnum.f32(float 0.000000e+00, float [[SQRT]]) 712; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]]) 713; CHECK-NEXT: ret float [[FABS]] 714; 715 %sqrt = call float @llvm.sqrt.f32(float %a) 716 %max = call float @llvm.maxnum.f32(float 0.0, float %sqrt) 717 %fabs = call float @llvm.fabs.f32(float %max) 718 ret float %fabs 719} 720 721define float @maxnum_with_negzero_op(float %a) { 722; CHECK-LABEL: @maxnum_with_negzero_op( 723; CHECK-NEXT: [[NNAN:%.*]] = call nnan float @llvm.sqrt.f32(float [[A:%.*]]) 724; CHECK-NEXT: [[FABSA:%.*]] = call float @llvm.fabs.f32(float [[NNAN]]) 725; CHECK-NEXT: [[MAX:%.*]] = call float @llvm.maxnum.f32(float -0.000000e+00, float [[FABSA]]) 726; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]]) 727; CHECK-NEXT: ret float [[FABS]] 728; 729 %nnan = call nnan float @llvm.sqrt.f32(float %a) 730 %fabsa = call float @llvm.fabs.f32(float %nnan) 731 %max = call float @llvm.maxnum.f32(float -0.0, float %fabsa) 732 %fabs = call float @llvm.fabs.f32(float %max) 733 ret float %fabs 734} 735 736define float @maxnum_with_negzero_op_commute(float %a) { 737; CHECK-LABEL: @maxnum_with_negzero_op_commute( 738; CHECK-NEXT: [[NNAN:%.*]] = call nnan float @llvm.sqrt.f32(float [[A:%.*]]) 739; CHECK-NEXT: [[FABSA:%.*]] = call float @llvm.fabs.f32(float [[NNAN]]) 740; CHECK-NEXT: [[MAX:%.*]] = call float @llvm.maxnum.f32(float [[FABSA]], float -0.000000e+00) 741; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]]) 742; CHECK-NEXT: ret float [[FABS]] 743; 744 %nnan = call nnan float @llvm.sqrt.f32(float %a) 745 %fabsa = call float @llvm.fabs.f32(float %nnan) 746 %max = call float @llvm.maxnum.f32(float %fabsa, float -0.0) 747 %fabs = call float @llvm.fabs.f32(float %max) 748 ret float %fabs 749} 750 751; If an operand is strictly greater than 0.0, we know the sign of the result of maxnum. 752 753define float @maxnum_with_pos_one_op(float %a) { 754; CHECK-LABEL: @maxnum_with_pos_one_op( 755; CHECK-NEXT: [[MAX:%.*]] = call float @llvm.maxnum.f32(float [[A:%.*]], float 1.000000e+00) 756; CHECK-NEXT: ret float [[MAX]] 757; 758 %max = call float @llvm.maxnum.f32(float %a, float 1.0) 759 %fabs = call float @llvm.fabs.f32(float %max) 760 ret float %fabs 761} 762