1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -instsimplify -S | FileCheck %s 3 4define <2 x float> @fsub_negzero_vec_undef_elts(<2 x float> %x) { 5; CHECK-LABEL: @fsub_negzero_vec_undef_elts( 6; CHECK-NEXT: ret <2 x float> [[X:%.*]] 7; 8 %r = fsub nsz <2 x float> %x, <float undef, float -0.0> 9 ret <2 x float> %r 10} 11 12; fsub -0.0, (fsub -0.0, X) ==> X 13define float @fsub_-0_-0_x(float %a) { 14; CHECK-LABEL: @fsub_-0_-0_x( 15; CHECK-NEXT: ret float [[A:%.*]] 16; 17 %t1 = fsub float -0.0, %a 18 %ret = fsub float -0.0, %t1 19 ret float %ret 20} 21 22define <2 x float> @fsub_-0_-0_x_vec(<2 x float> %a) { 23; CHECK-LABEL: @fsub_-0_-0_x_vec( 24; CHECK-NEXT: ret <2 x float> [[A:%.*]] 25; 26 %t1 = fsub <2 x float> <float -0.0, float -0.0>, %a 27 %ret = fsub <2 x float> <float -0.0, float -0.0>, %t1 28 ret <2 x float> %ret 29} 30 31define <2 x float> @fsub_-0_-0_x_vec_undef_elts(<2 x float> %a) { 32; CHECK-LABEL: @fsub_-0_-0_x_vec_undef_elts( 33; CHECK-NEXT: ret <2 x float> [[A:%.*]] 34; 35 %t1 = fsub <2 x float> <float undef, float -0.0>, %a 36 %ret = fsub <2 x float> <float -0.0, float undef>, %t1 37 ret <2 x float> %ret 38} 39 40; fsub 0.0, (fsub -0.0, X) != X 41define float @fsub_0_-0_x(float %a) { 42; CHECK-LABEL: @fsub_0_-0_x( 43; CHECK-NEXT: [[T1:%.*]] = fsub float 0.000000e+00, [[A:%.*]] 44; CHECK-NEXT: [[RET:%.*]] = fsub float -0.000000e+00, [[T1]] 45; CHECK-NEXT: ret float [[RET]] 46; 47 %t1 = fsub float 0.0, %a 48 %ret = fsub float -0.0, %t1 49 ret float %ret 50} 51 52; fsub -0.0, (fsub 0.0, X) != X 53define float @fsub_-0_0_x(float %a) { 54; CHECK-LABEL: @fsub_-0_0_x( 55; CHECK-NEXT: [[T1:%.*]] = fsub float -0.000000e+00, [[A:%.*]] 56; CHECK-NEXT: [[RET:%.*]] = fsub float 0.000000e+00, [[T1]] 57; CHECK-NEXT: ret float [[RET]] 58; 59 %t1 = fsub float -0.0, %a 60 %ret = fsub float 0.0, %t1 61 ret float %ret 62} 63 64; fsub X, 0 ==> X 65define float @fsub_x_0(float %x) { 66; CHECK-LABEL: @fsub_x_0( 67; CHECK-NEXT: ret float [[X:%.*]] 68; 69 %r = fsub float %x, 0.0 70 ret float %r 71} 72 73define <2 x float> @fsub_x_0_vec_undef(<2 x float> %x) { 74; CHECK-LABEL: @fsub_x_0_vec_undef( 75; CHECK-NEXT: ret <2 x float> [[X:%.*]] 76; 77 %r = fsub <2 x float> %x, <float undef, float 0.0> 78 ret <2 x float> %r 79} 80 81; fadd X, -0 ==> X 82define float @fadd_x_n0(float %a) { 83; CHECK-LABEL: @fadd_x_n0( 84; CHECK-NEXT: ret float [[A:%.*]] 85; 86 %ret = fadd float %a, -0.0 87 ret float %ret 88} 89 90define <2 x float> @fadd_x_n0_vec_undef_elt(<2 x float> %a) { 91; CHECK-LABEL: @fadd_x_n0_vec_undef_elt( 92; CHECK-NEXT: ret <2 x float> [[A:%.*]] 93; 94 %ret = fadd <2 x float> %a, <float -0.0, float undef> 95 ret <2 x float> %ret 96} 97 98; fmul X, 1.0 ==> X 99define double @fmul_X_1(double %a) { 100; CHECK-LABEL: @fmul_X_1( 101; CHECK-NEXT: ret double [[A:%.*]] 102; 103 %b = fmul double 1.0, %a 104 ret double %b 105} 106 107; PR2642 108define <4 x float> @fmul_X_1_vec(<4 x float> %x) { 109; CHECK-LABEL: @fmul_X_1_vec( 110; CHECK-NEXT: ret <4 x float> [[X:%.*]] 111; 112 %m = fmul <4 x float> %x, <float 1.0, float 1.0, float 1.0, float 1.0> 113 ret <4 x float> %m 114} 115 116; fdiv X, 1.0 ==> X 117define float @fdiv_x_1(float %a) { 118; CHECK-LABEL: @fdiv_x_1( 119; CHECK-NEXT: ret float [[A:%.*]] 120; 121 %ret = fdiv float %a, 1.0 122 ret float %ret 123} 124 125; We can't optimize away the fadd in this test because the input 126; value to the function and subsequently to the fadd may be -0.0. 127; In that one special case, the result of the fadd should be +0.0 128; rather than the first parameter of the fadd. 129 130; Fragile test warning: We need 6 sqrt calls to trigger the bug 131; because the internal logic has a magic recursion limit of 6. 132; This is presented without any explanation or ability to customize. 133 134declare float @sqrtf(float) 135 136define float @PR22688(float %x) { 137; CHECK-LABEL: @PR22688( 138; CHECK-NEXT: [[TMP1:%.*]] = call float @sqrtf(float [[X:%.*]]) 139; CHECK-NEXT: [[TMP2:%.*]] = call float @sqrtf(float [[TMP1]]) 140; CHECK-NEXT: [[TMP3:%.*]] = call float @sqrtf(float [[TMP2]]) 141; CHECK-NEXT: [[TMP4:%.*]] = call float @sqrtf(float [[TMP3]]) 142; CHECK-NEXT: [[TMP5:%.*]] = call float @sqrtf(float [[TMP4]]) 143; CHECK-NEXT: [[TMP6:%.*]] = call float @sqrtf(float [[TMP5]]) 144; CHECK-NEXT: [[TMP7:%.*]] = fadd float [[TMP6]], 0.000000e+00 145; CHECK-NEXT: ret float [[TMP7]] 146; 147 %1 = call float @sqrtf(float %x) 148 %2 = call float @sqrtf(float %1) 149 %3 = call float @sqrtf(float %2) 150 %4 = call float @sqrtf(float %3) 151 %5 = call float @sqrtf(float %4) 152 %6 = call float @sqrtf(float %5) 153 %7 = fadd float %6, 0.0 154 ret float %7 155} 156 157declare float @llvm.fabs.f32(float) 158declare <2 x float> @llvm.fabs.v2f32(<2 x float>) 159declare float @llvm.sqrt.f32(float) 160 161define float @fabs_select_positive_constants(i32 %c) { 162; CHECK-LABEL: @fabs_select_positive_constants( 163; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 164; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 1.000000e+00, float 2.000000e+00 165; CHECK-NEXT: ret float [[SELECT]] 166; 167 %cmp = icmp eq i32 %c, 0 168 %select = select i1 %cmp, float 1.0, float 2.0 169 %fabs = call float @llvm.fabs.f32(float %select) 170 ret float %fabs 171} 172 173define <2 x float> @fabs_select_positive_constants_vector(i32 %c) { 174; CHECK-LABEL: @fabs_select_positive_constants_vector( 175; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 176; 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> 177; CHECK-NEXT: ret <2 x float> [[SELECT]] 178; 179 %cmp = icmp eq i32 %c, 0 180 %select = select i1 %cmp, <2 x float> <float 1.0, float 1.0>, <2 x float> <float 2.0, float 2.0> 181 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 182 ret <2 x float> %fabs 183} 184 185define float @fabs_select_constant_variable(i32 %c, float %x) { 186; CHECK-LABEL: @fabs_select_constant_variable( 187; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 188; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 1.000000e+00, float [[X:%.*]] 189; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) 190; CHECK-NEXT: ret float [[FABS]] 191; 192 %cmp = icmp eq i32 %c, 0 193 %select = select i1 %cmp, float 1.0, float %x 194 %fabs = call float @llvm.fabs.f32(float %select) 195 ret float %fabs 196} 197 198define <2 x float> @fabs_select_constant_variable_vector(i32 %c, <2 x float> %x) { 199; CHECK-LABEL: @fabs_select_constant_variable_vector( 200; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 201; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 1.000000e+00, float 1.000000e+00>, <2 x float> [[X:%.*]] 202; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]]) 203; CHECK-NEXT: ret <2 x float> [[FABS]] 204; 205 %cmp = icmp eq i32 %c, 0 206 %select = select i1 %cmp, <2 x float> <float 1.0, float 1.0>, <2 x float> %x 207 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 208 ret <2 x float> %fabs 209} 210 211define float @fabs_select_neg0_pos0(i32 %c) { 212; CHECK-LABEL: @fabs_select_neg0_pos0( 213; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 214; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float -0.000000e+00, float 0.000000e+00 215; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) 216; CHECK-NEXT: ret float [[FABS]] 217; 218 %cmp = icmp eq i32 %c, 0 219 %select = select i1 %cmp, float -0.0, float 0.0 220 %fabs = call float @llvm.fabs.f32(float %select) 221 ret float %fabs 222} 223 224define <2 x float> @fabs_select_neg0_pos0_vector(i32 %c) { 225; CHECK-LABEL: @fabs_select_neg0_pos0_vector( 226; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 227; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float -0.000000e+00, float -0.000000e+00>, <2 x float> zeroinitializer 228; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]]) 229; CHECK-NEXT: ret <2 x float> [[FABS]] 230; 231 %cmp = icmp eq i32 %c, 0 232 %select = select i1 %cmp, <2 x float> <float -0.0, float -0.0>, <2 x float> <float 0.0, float 0.0> 233 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 234 ret <2 x float> %fabs 235} 236 237define float @fabs_select_neg0_neg1(i32 %c) { 238; CHECK-LABEL: @fabs_select_neg0_neg1( 239; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 240; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float -0.000000e+00, float -1.000000e+00 241; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) 242; CHECK-NEXT: ret float [[FABS]] 243; 244 %cmp = icmp eq i32 %c, 0 245 %select = select i1 %cmp, float -0.0, float -1.0 246 %fabs = call float @llvm.fabs.f32(float %select) 247 ret float %fabs 248} 249 250define <2 x float> @fabs_select_neg0_neg1_vector(i32 %c) { 251; CHECK-LABEL: @fabs_select_neg0_neg1_vector( 252; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 253; 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> 254; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]]) 255; CHECK-NEXT: ret <2 x float> [[FABS]] 256; 257 %cmp = icmp eq i32 %c, 0 258 %select = select i1 %cmp, <2 x float> <float -0.0, float -0.0>, <2 x float> <float -1.0, float -1.0> 259 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 260 ret <2 x float> %fabs 261} 262 263define float @fabs_select_nan_nan(i32 %c) { 264; CHECK-LABEL: @fabs_select_nan_nan( 265; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 266; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 0x7FF8000000000000, float 0x7FF8000100000000 267; CHECK-NEXT: ret float [[SELECT]] 268; 269 %cmp = icmp eq i32 %c, 0 270 %select = select i1 %cmp, float 0x7FF8000000000000, float 0x7FF8000100000000 271 %fabs = call float @llvm.fabs.f32(float %select) 272 ret float %fabs 273} 274 275define <2 x float> @fabs_select_nan_nan_vector(i32 %c) { 276; CHECK-LABEL: @fabs_select_nan_nan_vector( 277; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 278; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000> 279; CHECK-NEXT: ret <2 x float> [[SELECT]] 280; 281 %cmp = icmp eq i32 %c, 0 282 %select = select i1 %cmp, <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000> 283 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 284 ret <2 x float> %fabs 285} 286 287define float @fabs_select_negnan_nan(i32 %c) { 288; CHECK-LABEL: @fabs_select_negnan_nan( 289; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 290; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float 0x7FF8000000000000 291; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) 292; CHECK-NEXT: ret float [[FABS]] 293; 294 %cmp = icmp eq i32 %c, 0 295 %select = select i1 %cmp, float 0xFFF8000000000000, float 0x7FF8000000000000 296 %fabs = call float @llvm.fabs.f32(float %select) 297 ret float %fabs 298} 299 300define <2 x float> @fabs_select_negnan_nan_vector(i32 %c) { 301; CHECK-LABEL: @fabs_select_negnan_nan_vector( 302; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 303; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000> 304; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]]) 305; CHECK-NEXT: ret <2 x float> [[FABS]] 306; 307 %cmp = icmp eq i32 %c, 0 308 %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000> 309 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 310 ret <2 x float> %fabs 311} 312 313define float @fabs_select_negnan_negnan(i32 %c) { 314; CHECK-LABEL: @fabs_select_negnan_negnan( 315; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 316; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float 0x7FF8000100000000 317; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) 318; CHECK-NEXT: ret float [[FABS]] 319; 320 %cmp = icmp eq i32 %c, 0 321 %select = select i1 %cmp, float 0xFFF8000000000000, float 0x7FF8000100000000 322 %fabs = call float @llvm.fabs.f32(float %select) 323 ret float %fabs 324} 325 326define <2 x float> @fabs_select_negnan_negnan_vector(i32 %c) { 327; CHECK-LABEL: @fabs_select_negnan_negnan_vector( 328; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 329; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000> 330; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]]) 331; CHECK-NEXT: ret <2 x float> [[FABS]] 332; 333 %cmp = icmp eq i32 %c, 0 334 %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000> 335 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 336 ret <2 x float> %fabs 337} 338 339define float @fabs_select_negnan_negzero(i32 %c) { 340; CHECK-LABEL: @fabs_select_negnan_negzero( 341; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 342; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float -0.000000e+00 343; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) 344; CHECK-NEXT: ret float [[FABS]] 345; 346 %cmp = icmp eq i32 %c, 0 347 %select = select i1 %cmp, float 0xFFF8000000000000, float -0.0 348 %fabs = call float @llvm.fabs.f32(float %select) 349 ret float %fabs 350} 351 352define <2 x float> @fabs_select_negnan_negzero_vector(i32 %c) { 353; CHECK-LABEL: @fabs_select_negnan_negzero_vector( 354; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 355; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float -0.000000e+00, float -0.000000e+00> 356; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]]) 357; CHECK-NEXT: ret <2 x float> [[FABS]] 358; 359 %cmp = icmp eq i32 %c, 0 360 %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float -0.0, float -0.0> 361 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 362 ret <2 x float> %fabs 363} 364 365define float @fabs_select_negnan_zero(i32 %c) { 366; CHECK-LABEL: @fabs_select_negnan_zero( 367; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 368; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float 0.000000e+00 369; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) 370; CHECK-NEXT: ret float [[FABS]] 371; 372 %cmp = icmp eq i32 %c, 0 373 %select = select i1 %cmp, float 0xFFF8000000000000, float 0.0 374 %fabs = call float @llvm.fabs.f32(float %select) 375 ret float %fabs 376} 377 378define <2 x float> @fabs_select_negnan_zero_vector(i32 %c) { 379; CHECK-LABEL: @fabs_select_negnan_zero_vector( 380; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 381; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> zeroinitializer 382; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]]) 383; CHECK-NEXT: ret <2 x float> [[FABS]] 384; 385 %cmp = icmp eq i32 %c, 0 386 %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0.0, float 0.0> 387 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 388 ret <2 x float> %fabs 389} 390 391; The fabs can't be eliminated because llvm.sqrt.f32 may return -0 or NaN with 392; an arbitrary sign bit. 393define float @fabs_sqrt(float %a) { 394; CHECK-LABEL: @fabs_sqrt( 395; CHECK-NEXT: [[SQRT:%.*]] = call float @llvm.sqrt.f32(float [[A:%.*]]) 396; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]]) 397; CHECK-NEXT: ret float [[FABS]] 398; 399 %sqrt = call float @llvm.sqrt.f32(float %a) 400 %fabs = call float @llvm.fabs.f32(float %sqrt) 401 ret float %fabs 402} 403 404; The fabs can't be eliminated because the nnan sqrt may still return -0. 405define float @fabs_sqrt_nnan(float %a) { 406; CHECK-LABEL: @fabs_sqrt_nnan( 407; CHECK-NEXT: [[SQRT:%.*]] = call nnan float @llvm.sqrt.f32(float [[A:%.*]]) 408; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]]) 409; CHECK-NEXT: ret float [[FABS]] 410; 411 %sqrt = call nnan float @llvm.sqrt.f32(float %a) 412 %fabs = call float @llvm.fabs.f32(float %sqrt) 413 ret float %fabs 414} 415 416; The fabs can't be eliminated because the nsz sqrt may still return NaN. 417define float @fabs_sqrt_nsz(float %a) { 418; CHECK-LABEL: @fabs_sqrt_nsz( 419; CHECK-NEXT: [[SQRT:%.*]] = call nsz float @llvm.sqrt.f32(float [[A:%.*]]) 420; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]]) 421; CHECK-NEXT: ret float [[FABS]] 422; 423 %sqrt = call nsz float @llvm.sqrt.f32(float %a) 424 %fabs = call float @llvm.fabs.f32(float %sqrt) 425 ret float %fabs 426} 427 428; The fabs can be eliminated because we're nsz and nnan. 429define float @fabs_sqrt_nnan_nsz(float %a) { 430; CHECK-LABEL: @fabs_sqrt_nnan_nsz( 431; CHECK-NEXT: [[SQRT:%.*]] = call nnan nsz float @llvm.sqrt.f32(float [[A:%.*]]) 432; CHECK-NEXT: ret float [[SQRT]] 433; 434 %sqrt = call nnan nsz float @llvm.sqrt.f32(float %a) 435 %fabs = call float @llvm.fabs.f32(float %sqrt) 436 ret float %fabs 437} 438 439; The second fabs can be eliminated because the operand to sqrt cannot be -0. 440define float @fabs_sqrt_nnan_fabs(float %a) { 441; CHECK-LABEL: @fabs_sqrt_nnan_fabs( 442; CHECK-NEXT: [[B:%.*]] = call float @llvm.fabs.f32(float [[A:%.*]]) 443; CHECK-NEXT: [[SQRT:%.*]] = call nnan float @llvm.sqrt.f32(float [[B]]) 444; CHECK-NEXT: ret float [[SQRT]] 445; 446 %b = call float @llvm.fabs.f32(float %a) 447 %sqrt = call nnan float @llvm.sqrt.f32(float %b) 448 %fabs = call float @llvm.fabs.f32(float %sqrt) 449 ret float %fabs 450} 451 452define float @fabs_select_positive_constants_vector_extract(i32 %c) { 453; CHECK-LABEL: @fabs_select_positive_constants_vector_extract( 454; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 455; 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> 456; CHECK-NEXT: [[EXTRACT:%.*]] = extractelement <2 x float> [[SELECT]], i32 0 457; CHECK-NEXT: ret float [[EXTRACT]] 458; 459 %cmp = icmp eq i32 %c, 0 460 %select = select i1 %cmp, <2 x float> <float 1.0, float 1.0>, <2 x float> <float 2.0, float 2.0> 461 %extract = extractelement <2 x float> %select, i32 0 462 %fabs = call float @llvm.fabs.f32(float %extract) 463 ret float %fabs 464} 465 466declare double @llvm.minnum.f64(double, double) 467declare double @llvm.maxnum.f64(double, double) 468declare <2 x double> @llvm.minnum.v2f64(<2 x double>, <2 x double>) 469declare <2 x double> @llvm.maxnum.v2f64(<2 x double>, <2 x double>) 470 471; From the LangRef for minnum/maxnum: 472; "follows the IEEE-754 semantics for maxNum, which also match for libm’s fmax. 473; If either operand is a NaN, returns the other non-NaN operand." 474 475define double @maxnum_nan_op0(double %x) { 476; CHECK-LABEL: @maxnum_nan_op0( 477; CHECK-NEXT: ret double [[X:%.*]] 478; 479 %r = call double @llvm.maxnum.f64(double 0x7ff8000000000000, double %x) 480 ret double %r 481} 482 483define double @maxnum_nan_op1(double %x) { 484; CHECK-LABEL: @maxnum_nan_op1( 485; CHECK-NEXT: ret double [[X:%.*]] 486; 487 %r = call double @llvm.maxnum.f64(double %x, double 0x7ff800000000dead) 488 ret double %r 489} 490 491define double @minnum_nan_op0(double %x) { 492; CHECK-LABEL: @minnum_nan_op0( 493; CHECK-NEXT: ret double [[X:%.*]] 494; 495 %r = call double @llvm.minnum.f64(double 0x7ff8000dead00000, double %x) 496 ret double %r 497} 498 499define double @minnum_nan_op1(double %x) { 500; CHECK-LABEL: @minnum_nan_op1( 501; CHECK-NEXT: ret double [[X:%.*]] 502; 503 %r = call double @llvm.minnum.f64(double %x, double 0x7ff800dead00dead) 504 ret double %r 505} 506 507define <2 x double> @maxnum_nan_op0_vec(<2 x double> %x) { 508; CHECK-LABEL: @maxnum_nan_op0_vec( 509; CHECK-NEXT: ret <2 x double> [[X:%.*]] 510; 511 %r = call <2 x double> @llvm.maxnum.v2f64(<2 x double> <double 0x7ff8000000000000, double undef>, <2 x double> %x) 512 ret <2 x double> %r 513} 514 515define <2 x double> @maxnum_nan_op1_vec(<2 x double> %x) { 516; CHECK-LABEL: @maxnum_nan_op1_vec( 517; CHECK-NEXT: ret <2 x double> [[X:%.*]] 518; 519 %r = call <2 x double> @llvm.maxnum.v2f64(<2 x double> %x, <2 x double> <double 0x7ff800000000dead, double 0x7ff8ffffffffffff>) 520 ret <2 x double> %r 521} 522 523define <2 x double> @minnum_nan_op0_vec(<2 x double> %x) { 524; CHECK-LABEL: @minnum_nan_op0_vec( 525; CHECK-NEXT: ret <2 x double> [[X:%.*]] 526; 527 %r = call <2 x double> @llvm.minnum.v2f64(<2 x double> <double undef, double 0x7ff8000dead00000>, <2 x double> %x) 528 ret <2 x double> %r 529} 530 531define <2 x double> @minnum_nan_op1_vec(<2 x double> %x) { 532; CHECK-LABEL: @minnum_nan_op1_vec( 533; CHECK-NEXT: ret <2 x double> [[X:%.*]] 534; 535 %r = call <2 x double> @llvm.minnum.v2f64(<2 x double> %x, <2 x double> <double 0x7ff800dead00dead, double 0x7ff800dead00dead>) 536 ret <2 x double> %r 537} 538 539