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 float @llvm.minnum.f32(float, float) 467declare float @llvm.maxnum.f32(float, float) 468declare double @llvm.minnum.f64(double, double) 469declare double @llvm.maxnum.f64(double, double) 470declare <2 x double> @llvm.minnum.v2f64(<2 x double>, <2 x double>) 471declare <2 x double> @llvm.maxnum.v2f64(<2 x double>, <2 x double>) 472 473; From the LangRef for minnum/maxnum: 474; "If either operand is a NaN, returns the other non-NaN operand." 475 476define double @maxnum_nan_op0(double %x) { 477; CHECK-LABEL: @maxnum_nan_op0( 478; CHECK-NEXT: ret double [[X:%.*]] 479; 480 %r = call double @llvm.maxnum.f64(double 0x7ff8000000000000, double %x) 481 ret double %r 482} 483 484define double @maxnum_nan_op1(double %x) { 485; CHECK-LABEL: @maxnum_nan_op1( 486; CHECK-NEXT: ret double [[X:%.*]] 487; 488 %r = call double @llvm.maxnum.f64(double %x, double 0x7ff800000000dead) 489 ret double %r 490} 491 492define double @minnum_nan_op0(double %x) { 493; CHECK-LABEL: @minnum_nan_op0( 494; CHECK-NEXT: ret double [[X:%.*]] 495; 496 %r = call double @llvm.minnum.f64(double 0x7ff8000dead00000, double %x) 497 ret double %r 498} 499 500define double @minnum_nan_op1(double %x) { 501; CHECK-LABEL: @minnum_nan_op1( 502; CHECK-NEXT: ret double [[X:%.*]] 503; 504 %r = call double @llvm.minnum.f64(double %x, double 0x7ff800dead00dead) 505 ret double %r 506} 507 508define <2 x double> @maxnum_nan_op0_vec(<2 x double> %x) { 509; CHECK-LABEL: @maxnum_nan_op0_vec( 510; CHECK-NEXT: ret <2 x double> [[X:%.*]] 511; 512 %r = call <2 x double> @llvm.maxnum.v2f64(<2 x double> <double 0x7ff8000000000000, double undef>, <2 x double> %x) 513 ret <2 x double> %r 514} 515 516define <2 x double> @maxnum_nan_op1_vec(<2 x double> %x) { 517; CHECK-LABEL: @maxnum_nan_op1_vec( 518; CHECK-NEXT: ret <2 x double> [[X:%.*]] 519; 520 %r = call <2 x double> @llvm.maxnum.v2f64(<2 x double> %x, <2 x double> <double 0x7ff800000000dead, double 0x7ff8ffffffffffff>) 521 ret <2 x double> %r 522} 523 524define <2 x double> @minnum_nan_op0_vec(<2 x double> %x) { 525; CHECK-LABEL: @minnum_nan_op0_vec( 526; CHECK-NEXT: ret <2 x double> [[X:%.*]] 527; 528 %r = call <2 x double> @llvm.minnum.v2f64(<2 x double> <double undef, double 0x7ff8000dead00000>, <2 x double> %x) 529 ret <2 x double> %r 530} 531 532define <2 x double> @minnum_nan_op1_vec(<2 x double> %x) { 533; CHECK-LABEL: @minnum_nan_op1_vec( 534; CHECK-NEXT: ret <2 x double> [[X:%.*]] 535; 536 %r = call <2 x double> @llvm.minnum.v2f64(<2 x double> %x, <2 x double> <double 0x7ff800dead00dead, double 0x7ff800dead00dead>) 537 ret <2 x double> %r 538} 539 540define float @maxnum_undef_op1(float %x) { 541; CHECK-LABEL: @maxnum_undef_op1( 542; CHECK-NEXT: ret float [[X:%.*]] 543; 544 %val = call float @llvm.maxnum.f32(float %x, float undef) 545 ret float %val 546} 547 548define float @maxnum_undef_op0(float %x) { 549; CHECK-LABEL: @maxnum_undef_op0( 550; CHECK-NEXT: ret float [[X:%.*]] 551; 552 %val = call float @llvm.maxnum.f32(float undef, float %x) 553 ret float %val 554} 555 556define float @minnum_undef_op1(float %x) { 557; CHECK-LABEL: @minnum_undef_op1( 558; CHECK-NEXT: ret float [[X:%.*]] 559; 560 %val = call float @llvm.minnum.f32(float %x, float undef) 561 ret float %val 562} 563 564define float @minnum_undef_op0(float %x) { 565; CHECK-LABEL: @minnum_undef_op0( 566; CHECK-NEXT: ret float [[X:%.*]] 567; 568 %val = call float @llvm.minnum.f32(float undef, float %x) 569 ret float %val 570} 571 572define float @minnum_undef_undef(float %x) { 573; CHECK-LABEL: @minnum_undef_undef( 574; CHECK-NEXT: ret float undef 575; 576 %val = call float @llvm.minnum.f32(float undef, float undef) 577 ret float %val 578} 579 580define float @maxnum_undef_undef(float %x) { 581; CHECK-LABEL: @maxnum_undef_undef( 582; CHECK-NEXT: ret float undef 583; 584 %val = call float @llvm.maxnum.f32(float undef, float undef) 585 ret float %val 586} 587 588define float @minnum_same_args(float %x) { 589; CHECK-LABEL: @minnum_same_args( 590; CHECK-NEXT: ret float [[X:%.*]] 591; 592 %y = call float @llvm.minnum.f32(float %x, float %x) 593 ret float %y 594} 595 596define float @maxnum_same_args(float %x) { 597; CHECK-LABEL: @maxnum_same_args( 598; CHECK-NEXT: ret float [[X:%.*]] 599; 600 %y = call float @llvm.maxnum.f32(float %x, float %x) 601 ret float %y 602} 603 604define float @minnum_x_minnum_x_y(float %x, float %y) { 605; CHECK-LABEL: @minnum_x_minnum_x_y( 606; CHECK-NEXT: [[A:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]]) 607; CHECK-NEXT: ret float [[A]] 608; 609 %a = call float @llvm.minnum.f32(float %x, float %y) 610 %b = call float @llvm.minnum.f32(float %x, float %a) 611 ret float %b 612} 613 614define float @minnum_y_minnum_x_y(float %x, float %y) { 615; CHECK-LABEL: @minnum_y_minnum_x_y( 616; CHECK-NEXT: [[A:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]]) 617; CHECK-NEXT: ret float [[A]] 618; 619 %a = call float @llvm.minnum.f32(float %x, float %y) 620 %b = call float @llvm.minnum.f32(float %y, float %a) 621 ret float %b 622} 623 624define float @minnum_x_y_minnum_x(float %x, float %y) { 625; CHECK-LABEL: @minnum_x_y_minnum_x( 626; CHECK-NEXT: [[A:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]]) 627; CHECK-NEXT: ret float [[A]] 628; 629 %a = call float @llvm.minnum.f32(float %x, float %y) 630 %b = call float @llvm.minnum.f32(float %a, float %x) 631 ret float %b 632} 633 634define float @minnum_x_y_minnum_y(float %x, float %y) { 635; CHECK-LABEL: @minnum_x_y_minnum_y( 636; CHECK-NEXT: [[A:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]]) 637; CHECK-NEXT: ret float [[A]] 638; 639 %a = call float @llvm.minnum.f32(float %x, float %y) 640 %b = call float @llvm.minnum.f32(float %a, float %y) 641 ret float %b 642} 643 644; negative test 645 646define float @minnum_z_minnum_x_y(float %x, float %y, float %z) { 647; CHECK-LABEL: @minnum_z_minnum_x_y( 648; CHECK-NEXT: [[A:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]]) 649; CHECK-NEXT: [[B:%.*]] = call float @llvm.minnum.f32(float [[Z:%.*]], float [[A]]) 650; CHECK-NEXT: ret float [[B]] 651; 652 %a = call float @llvm.minnum.f32(float %x, float %y) 653 %b = call float @llvm.minnum.f32(float %z, float %a) 654 ret float %b 655} 656 657; negative test 658 659define float @minnum_x_y_minnum_z(float %x, float %y, float %z) { 660; CHECK-LABEL: @minnum_x_y_minnum_z( 661; CHECK-NEXT: [[A:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]]) 662; CHECK-NEXT: [[B:%.*]] = call float @llvm.minnum.f32(float [[A]], float [[Z:%.*]]) 663; CHECK-NEXT: ret float [[B]] 664; 665 %a = call float @llvm.minnum.f32(float %x, float %y) 666 %b = call float @llvm.minnum.f32(float %a, float %z) 667 ret float %b 668} 669 670; minnum(X, -INF) --> -INF 671 672define float @minnum_neginf(float %x) { 673; CHECK-LABEL: @minnum_neginf( 674; CHECK-NEXT: ret float 0xFFF0000000000000 675; 676 %val = call float @llvm.minnum.f32(float %x, float 0xFFF0000000000000) 677 ret float %val 678} 679 680define <2 x double> @minnum_neginf_commute_vec(<2 x double> %x) { 681; CHECK-LABEL: @minnum_neginf_commute_vec( 682; CHECK-NEXT: ret <2 x double> <double 0xFFF0000000000000, double 0xFFF0000000000000> 683; 684 %r = call <2 x double> @llvm.minnum.v2f64(<2 x double> <double 0xFFF0000000000000, double 0xFFF0000000000000>, <2 x double> %x) 685 ret <2 x double> %r 686} 687 688; negative test 689 690define float @minnum_inf(float %x) { 691; CHECK-LABEL: @minnum_inf( 692; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.minnum.f32(float 0x7FF0000000000000, float [[X:%.*]]) 693; CHECK-NEXT: ret float [[VAL]] 694; 695 %val = call float @llvm.minnum.f32(float 0x7FF0000000000000, float %x) 696 ret float %val 697} 698define float @maxnum_x_maxnum_x_y(float %x, float %y) { 699; CHECK-LABEL: @maxnum_x_maxnum_x_y( 700; CHECK-NEXT: [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]]) 701; CHECK-NEXT: ret float [[A]] 702; 703 %a = call float @llvm.maxnum.f32(float %x, float %y) 704 %b = call float @llvm.maxnum.f32(float %x, float %a) 705 ret float %b 706} 707 708define float @maxnum_y_maxnum_x_y(float %x, float %y) { 709; CHECK-LABEL: @maxnum_y_maxnum_x_y( 710; CHECK-NEXT: [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]]) 711; CHECK-NEXT: ret float [[A]] 712; 713 %a = call float @llvm.maxnum.f32(float %x, float %y) 714 %b = call float @llvm.maxnum.f32(float %y, float %a) 715 ret float %b 716} 717 718define float @maxnum_x_y_maxnum_x(float %x, float %y) { 719; CHECK-LABEL: @maxnum_x_y_maxnum_x( 720; CHECK-NEXT: [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]]) 721; CHECK-NEXT: ret float [[A]] 722; 723 %a = call float @llvm.maxnum.f32(float %x, float %y) 724 %b = call float @llvm.maxnum.f32(float %a, float %x) 725 ret float %b 726} 727 728define float @maxnum_x_y_maxnum_y(float %x, float %y) { 729; CHECK-LABEL: @maxnum_x_y_maxnum_y( 730; CHECK-NEXT: [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]]) 731; CHECK-NEXT: ret float [[A]] 732; 733 %a = call float @llvm.maxnum.f32(float %x, float %y) 734 %b = call float @llvm.maxnum.f32(float %a, float %y) 735 ret float %b 736} 737 738; negative test 739 740define float @maxnum_z_maxnum_x_y(float %x, float %y, float %z) { 741; CHECK-LABEL: @maxnum_z_maxnum_x_y( 742; CHECK-NEXT: [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]]) 743; CHECK-NEXT: [[B:%.*]] = call float @llvm.maxnum.f32(float [[Z:%.*]], float [[A]]) 744; CHECK-NEXT: ret float [[B]] 745; 746 %a = call float @llvm.maxnum.f32(float %x, float %y) 747 %b = call float @llvm.maxnum.f32(float %z, float %a) 748 ret float %b 749} 750 751; negative test 752 753define float @maxnum_x_y_maxnum_z(float %x, float %y, float %z) { 754; CHECK-LABEL: @maxnum_x_y_maxnum_z( 755; CHECK-NEXT: [[A:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]]) 756; CHECK-NEXT: [[B:%.*]] = call float @llvm.maxnum.f32(float [[A]], float [[Z:%.*]]) 757; CHECK-NEXT: ret float [[B]] 758; 759 %a = call float @llvm.maxnum.f32(float %x, float %y) 760 %b = call float @llvm.maxnum.f32(float %a, float %z) 761 ret float %b 762} 763 764; maxnum(X, INF) --> INF 765 766define <2 x double> @maxnum_inf(<2 x double> %x) { 767; CHECK-LABEL: @maxnum_inf( 768; CHECK-NEXT: ret <2 x double> <double 0x7FF0000000000000, double 0x7FF0000000000000> 769; 770 %val = call <2 x double> @llvm.maxnum.v2f64(<2 x double> %x, <2 x double><double 0x7FF0000000000000, double 0x7FF0000000000000>) 771 ret <2 x double> %val 772} 773 774define float @maxnum_inf_commute(float %x) { 775; CHECK-LABEL: @maxnum_inf_commute( 776; CHECK-NEXT: ret float 0x7FF0000000000000 777; 778 %val = call float @llvm.maxnum.f32(float 0x7FF0000000000000, float %x) 779 ret float %val 780} 781 782; negative test 783 784define float @maxnum_neginf(float %x) { 785; CHECK-LABEL: @maxnum_neginf( 786; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.maxnum.f32(float 0xFFF0000000000000, float [[X:%.*]]) 787; CHECK-NEXT: ret float [[VAL]] 788; 789 %val = call float @llvm.maxnum.f32(float 0xFFF0000000000000, float %x) 790 ret float %val 791} 792 793declare float @llvm.minimum.f32(float, float) 794declare float @llvm.maximum.f32(float, float) 795declare double @llvm.minimum.f64(double, double) 796declare double @llvm.maximum.f64(double, double) 797declare <2 x double> @llvm.minimum.v2f64(<2 x double>, <2 x double>) 798declare <2 x double> @llvm.maximum.v2f64(<2 x double>, <2 x double>) 799 800; From the LangRef for minimum/maximum: 801; "If either operand is a NaN, returns NaN." 802 803define double @maximum_nan_op0(double %x) { 804; CHECK-LABEL: @maximum_nan_op0( 805; CHECK-NEXT: ret double 0x7FF8000000000000 806; 807 %r = call double @llvm.maximum.f64(double 0x7ff8000000000000, double %x) 808 ret double %r 809} 810 811define double @maximum_nan_op1(double %x) { 812; CHECK-LABEL: @maximum_nan_op1( 813; CHECK-NEXT: ret double 0x7FF800000000DEAD 814; 815 %r = call double @llvm.maximum.f64(double %x, double 0x7ff800000000dead) 816 ret double %r 817} 818 819define double @minimum_nan_op0(double %x) { 820; CHECK-LABEL: @minimum_nan_op0( 821; CHECK-NEXT: ret double 0x7FF8000DEAD00000 822; 823 %r = call double @llvm.minimum.f64(double 0x7ff8000dead00000, double %x) 824 ret double %r 825} 826 827define double @minimum_nan_op1(double %x) { 828; CHECK-LABEL: @minimum_nan_op1( 829; CHECK-NEXT: ret double 0x7FF800DEAD00DEAD 830; 831 %r = call double @llvm.minimum.f64(double %x, double 0x7ff800dead00dead) 832 ret double %r 833} 834 835define <2 x double> @maximum_nan_op0_vec(<2 x double> %x) { 836; CHECK-LABEL: @maximum_nan_op0_vec( 837; CHECK-NEXT: ret <2 x double> <double 0x7FF8000000000000, double undef> 838; 839 %r = call <2 x double> @llvm.maximum.v2f64(<2 x double> <double 0x7ff8000000000000, double undef>, <2 x double> %x) 840 ret <2 x double> %r 841} 842 843define <2 x double> @maximum_nan_op1_vec(<2 x double> %x) { 844; CHECK-LABEL: @maximum_nan_op1_vec( 845; CHECK-NEXT: ret <2 x double> <double 0x7FF800000000DEAD, double 0x7FF8FFFFFFFFFFFF> 846; 847 %r = call <2 x double> @llvm.maximum.v2f64(<2 x double> %x, <2 x double> <double 0x7ff800000000dead, double 0x7ff8ffffffffffff>) 848 ret <2 x double> %r 849} 850 851define <2 x double> @minimum_nan_op0_vec(<2 x double> %x) { 852; CHECK-LABEL: @minimum_nan_op0_vec( 853; CHECK-NEXT: ret <2 x double> <double undef, double 0x7FF8000DEAD00000> 854; 855 %r = call <2 x double> @llvm.minimum.v2f64(<2 x double> <double undef, double 0x7ff8000dead00000>, <2 x double> %x) 856 ret <2 x double> %r 857} 858 859define <2 x double> @minimum_nan_op1_vec(<2 x double> %x) { 860; CHECK-LABEL: @minimum_nan_op1_vec( 861; CHECK-NEXT: ret <2 x double> <double 0x7FF800DEAD00DEAD, double 0x7FF800DEAD00DEAD> 862; 863 %r = call <2 x double> @llvm.minimum.v2f64(<2 x double> %x, <2 x double> <double 0x7ff800dead00dead, double 0x7ff800dead00dead>) 864 ret <2 x double> %r 865} 866 867define float @maximum_undef_op1(float %x) { 868; CHECK-LABEL: @maximum_undef_op1( 869; CHECK-NEXT: ret float [[X:%.*]] 870; 871 %val = call float @llvm.maximum.f32(float %x, float undef) 872 ret float %val 873} 874 875define float @maximum_undef_op0(float %x) { 876; CHECK-LABEL: @maximum_undef_op0( 877; CHECK-NEXT: ret float [[X:%.*]] 878; 879 %val = call float @llvm.maximum.f32(float undef, float %x) 880 ret float %val 881} 882 883define float @minimum_undef_op1(float %x) { 884; CHECK-LABEL: @minimum_undef_op1( 885; CHECK-NEXT: ret float [[X:%.*]] 886; 887 %val = call float @llvm.minimum.f32(float %x, float undef) 888 ret float %val 889} 890 891define float @minimum_undef_op0(float %x) { 892; CHECK-LABEL: @minimum_undef_op0( 893; CHECK-NEXT: ret float [[X:%.*]] 894; 895 %val = call float @llvm.minimum.f32(float undef, float %x) 896 ret float %val 897} 898 899define float @minimum_undef_undef(float %x) { 900; CHECK-LABEL: @minimum_undef_undef( 901; CHECK-NEXT: ret float undef 902; 903 %val = call float @llvm.minimum.f32(float undef, float undef) 904 ret float %val 905} 906 907define float @maximum_undef_undef(float %x) { 908; CHECK-LABEL: @maximum_undef_undef( 909; CHECK-NEXT: ret float undef 910; 911 %val = call float @llvm.maximum.f32(float undef, float undef) 912 ret float %val 913} 914 915define float @minimum_same_args(float %x) { 916; CHECK-LABEL: @minimum_same_args( 917; CHECK-NEXT: ret float [[X:%.*]] 918; 919 %y = call float @llvm.minimum.f32(float %x, float %x) 920 ret float %y 921} 922 923define float @maximum_same_args(float %x) { 924; CHECK-LABEL: @maximum_same_args( 925; CHECK-NEXT: ret float [[X:%.*]] 926; 927 %y = call float @llvm.maximum.f32(float %x, float %x) 928 ret float %y 929} 930 931define float @minimum_x_minimum_x_y(float %x, float %y) { 932; CHECK-LABEL: @minimum_x_minimum_x_y( 933; CHECK-NEXT: [[A:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]]) 934; CHECK-NEXT: ret float [[A]] 935; 936 %a = call float @llvm.minimum.f32(float %x, float %y) 937 %b = call float @llvm.minimum.f32(float %x, float %a) 938 ret float %b 939} 940 941define float @minimum_y_minimum_x_y(float %x, float %y) { 942; CHECK-LABEL: @minimum_y_minimum_x_y( 943; CHECK-NEXT: [[A:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]]) 944; CHECK-NEXT: ret float [[A]] 945; 946 %a = call float @llvm.minimum.f32(float %x, float %y) 947 %b = call float @llvm.minimum.f32(float %y, float %a) 948 ret float %b 949} 950 951define float @minimum_x_y_minimum_x(float %x, float %y) { 952; CHECK-LABEL: @minimum_x_y_minimum_x( 953; CHECK-NEXT: [[A:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]]) 954; CHECK-NEXT: ret float [[A]] 955; 956 %a = call float @llvm.minimum.f32(float %x, float %y) 957 %b = call float @llvm.minimum.f32(float %a, float %x) 958 ret float %b 959} 960 961define float @minimum_x_y_minimum_y(float %x, float %y) { 962; CHECK-LABEL: @minimum_x_y_minimum_y( 963; CHECK-NEXT: [[A:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]]) 964; CHECK-NEXT: ret float [[A]] 965; 966 %a = call float @llvm.minimum.f32(float %x, float %y) 967 %b = call float @llvm.minimum.f32(float %a, float %y) 968 ret float %b 969} 970 971; negative test 972 973define float @minimum_z_minimum_x_y(float %x, float %y, float %z) { 974; CHECK-LABEL: @minimum_z_minimum_x_y( 975; CHECK-NEXT: [[A:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]]) 976; CHECK-NEXT: [[B:%.*]] = call float @llvm.minimum.f32(float [[Z:%.*]], float [[A]]) 977; CHECK-NEXT: ret float [[B]] 978; 979 %a = call float @llvm.minimum.f32(float %x, float %y) 980 %b = call float @llvm.minimum.f32(float %z, float %a) 981 ret float %b 982} 983 984; negative test 985 986define float @minimum_x_y_minimum_z(float %x, float %y, float %z) { 987; CHECK-LABEL: @minimum_x_y_minimum_z( 988; CHECK-NEXT: [[A:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]]) 989; CHECK-NEXT: [[B:%.*]] = call float @llvm.minimum.f32(float [[A]], float [[Z:%.*]]) 990; CHECK-NEXT: ret float [[B]] 991; 992 %a = call float @llvm.minimum.f32(float %x, float %y) 993 %b = call float @llvm.minimum.f32(float %a, float %z) 994 ret float %b 995} 996 997; minimum(X, -INF) --> -INF 998 999define float @minimum_neginf(float %x) { 1000; CHECK-LABEL: @minimum_neginf( 1001; CHECK-NEXT: ret float 0xFFF0000000000000 1002; 1003 %val = call float @llvm.minimum.f32(float %x, float 0xFFF0000000000000) 1004 ret float %val 1005} 1006 1007define <2 x double> @minimum_neginf_commute_vec(<2 x double> %x) { 1008; CHECK-LABEL: @minimum_neginf_commute_vec( 1009; CHECK-NEXT: ret <2 x double> <double 0xFFF0000000000000, double 0xFFF0000000000000> 1010; 1011 %r = call <2 x double> @llvm.minimum.v2f64(<2 x double> <double 0xFFF0000000000000, double 0xFFF0000000000000>, <2 x double> %x) 1012 ret <2 x double> %r 1013} 1014 1015; negative test 1016 1017define float @minimum_inf(float %x) { 1018; CHECK-LABEL: @minimum_inf( 1019; CHECK-NEXT: [[VAL:%.*]] = call float @llvm.minimum.f32(float 0x7FF0000000000000, float [[X:%.*]]) 1020; CHECK-NEXT: ret float [[VAL]] 1021; 1022 %val = call float @llvm.minimum.f32(float 0x7FF0000000000000, float %x) 1023 ret float %val 1024} 1025define float @maximum_x_maximum_x_y(float %x, float %y) { 1026; CHECK-LABEL: @maximum_x_maximum_x_y( 1027; CHECK-NEXT: [[A:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]]) 1028; CHECK-NEXT: ret float [[A]] 1029; 1030 %a = call float @llvm.maximum.f32(float %x, float %y) 1031 %b = call float @llvm.maximum.f32(float %x, float %a) 1032 ret float %b 1033} 1034 1035define float @maximum_y_maximum_x_y(float %x, float %y) { 1036; CHECK-LABEL: @maximum_y_maximum_x_y( 1037; CHECK-NEXT: [[A:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]]) 1038; CHECK-NEXT: ret float [[A]] 1039; 1040 %a = call float @llvm.maximum.f32(float %x, float %y) 1041 %b = call float @llvm.maximum.f32(float %y, float %a) 1042 ret float %b 1043} 1044 1045define float @maximum_x_y_maximum_x(float %x, float %y) { 1046; CHECK-LABEL: @maximum_x_y_maximum_x( 1047; CHECK-NEXT: [[A:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]]) 1048; CHECK-NEXT: ret float [[A]] 1049; 1050 %a = call float @llvm.maximum.f32(float %x, float %y) 1051 %b = call float @llvm.maximum.f32(float %a, float %x) 1052 ret float %b 1053} 1054 1055define float @maximum_x_y_maximum_y(float %x, float %y) { 1056; CHECK-LABEL: @maximum_x_y_maximum_y( 1057; CHECK-NEXT: [[A:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]]) 1058; CHECK-NEXT: ret float [[A]] 1059; 1060 %a = call float @llvm.maximum.f32(float %x, float %y) 1061 %b = call float @llvm.maximum.f32(float %a, float %y) 1062 ret float %b 1063} 1064 1065; negative test 1066 1067define float @maximum_z_maximum_x_y(float %x, float %y, float %z) { 1068; CHECK-LABEL: @maximum_z_maximum_x_y( 1069; CHECK-NEXT: [[A:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]]) 1070; CHECK-NEXT: [[B:%.*]] = call float @llvm.maximum.f32(float [[Z:%.*]], float [[A]]) 1071; CHECK-NEXT: ret float [[B]] 1072; 1073 %a = call float @llvm.maximum.f32(float %x, float %y) 1074 %b = call float @llvm.maximum.f32(float %z, float %a) 1075 ret float %b 1076} 1077 1078; negative test 1079 1080define float @maximum_x_y_maximum_z(float %x, float %y, float %z) { 1081; CHECK-LABEL: @maximum_x_y_maximum_z( 1082; CHECK-NEXT: [[A:%.*]] = call float @llvm.maximum.f32(float [[X:%.*]], float [[Y:%.*]]) 1083; CHECK-NEXT: [[B:%.*]] = call float @llvm.maximum.f32(float [[A]], float [[Z:%.*]]) 1084; CHECK-NEXT: ret float [[B]] 1085; 1086 %a = call float @llvm.maximum.f32(float %x, float %y) 1087 %b = call float @llvm.maximum.f32(float %a, float %z) 1088 ret float %b 1089} 1090 1091; maximum(X, INF) --> INF 1092 1093define <2 x double> @maximum_inf(<2 x double> %x) { 1094; CHECK-LABEL: @maximum_inf( 1095; CHECK-NEXT: ret <2 x double> <double 0x7FF0000000000000, double 0x7FF0000000000000> 1096; 1097 %val = call <2 x double> @llvm.maximum.v2f64(<2 x double> %x, <2 x double><double 0x7FF0000000000000, double 0x7FF0000000000000>) 1098 ret <2 x double> %val 1099} 1100 1101define float @maximum_inf_commute(float %x) { 1102; CHECK-LABEL: @maximum_inf_commute( 1103; CHECK-NEXT: ret float 0x7FF0000000000000 1104; 1105 %val = call float @llvm.maximum.f32(float 0x7FF0000000000000, float %x) 1106 ret float %val 1107} 1108 1109; Y - (Y - X) --> X 1110 1111define float @fsub_fsub_common_op(float %x, float %y) { 1112; CHECK-LABEL: @fsub_fsub_common_op( 1113; CHECK-NEXT: ret float [[X:%.*]] 1114; 1115 %s = fsub float %y, %x 1116 %r = fsub reassoc nsz float %y, %s 1117 ret float %r 1118} 1119 1120define <2 x float> @fsub_fsub_common_op_vec(<2 x float> %x, <2 x float> %y) { 1121; CHECK-LABEL: @fsub_fsub_common_op_vec( 1122; CHECK-NEXT: ret <2 x float> [[X:%.*]] 1123; 1124 %s = fsub <2 x float> %y, %x 1125 %r = fsub reassoc nsz <2 x float> %y, %s 1126 ret <2 x float> %r 1127} 1128 1129; Negative test - fsub is not commutative. 1130; Y - (X - Y) --> (Y - X) + Y (canonicalized) 1131 1132define float @fsub_fsub_wrong_common_op(float %x, float %y) { 1133; CHECK-LABEL: @fsub_fsub_wrong_common_op( 1134; CHECK-NEXT: [[S:%.*]] = fsub float [[X:%.*]], [[Y:%.*]] 1135; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz float [[Y]], [[S]] 1136; CHECK-NEXT: ret float [[R]] 1137; 1138 %s = fsub float %x, %y 1139 %r = fsub reassoc nsz float %y, %s 1140 ret float %r 1141} 1142 1143; Negative test - negated operand needed. 1144; (Y - X) - Y --> -X 1145 1146define float @fsub_fsub_common_op_wrong_commute(float %x, float %y) { 1147; CHECK-LABEL: @fsub_fsub_common_op_wrong_commute( 1148; CHECK-NEXT: [[S:%.*]] = fsub float [[Y:%.*]], [[X:%.*]] 1149; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz float [[S]], [[Y]] 1150; CHECK-NEXT: ret float [[R]] 1151; 1152 %s = fsub float %y, %x 1153 %r = fsub reassoc nsz float %s, %y 1154 ret float %r 1155} 1156 1157; Negative test - fsub is not commutative. 1158; (X - Y) - Y --> ? 1159 1160define float @fsub_fsub_wrong_common_op_wrong_commute(float %x, float %y) { 1161; CHECK-LABEL: @fsub_fsub_wrong_common_op_wrong_commute( 1162; CHECK-NEXT: [[S:%.*]] = fsub float [[X:%.*]], [[Y:%.*]] 1163; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz float [[S]], [[Y]] 1164; CHECK-NEXT: ret float [[R]] 1165; 1166 %s = fsub float %x, %y 1167 %r = fsub reassoc nsz float %s, %y 1168 ret float %r 1169} 1170 1171; (Y + X) - Y --> X 1172 1173define float @fadd_fsub_common_op(float %x, float %y) { 1174; CHECK-LABEL: @fadd_fsub_common_op( 1175; CHECK-NEXT: ret float [[X:%.*]] 1176; 1177 %a = fadd float %y, %x 1178 %r = fsub reassoc nsz float %a, %y 1179 ret float %r 1180} 1181 1182; (X + Y) - Y --> X 1183 1184define <2 x float> @fadd_fsub_common_op_commute_vec(<2 x float> %x, <2 x float> %y) { 1185; CHECK-LABEL: @fadd_fsub_common_op_commute_vec( 1186; CHECK-NEXT: ret <2 x float> [[X:%.*]] 1187; 1188 %a = fadd <2 x float> %x, %y 1189 %r = fsub reassoc nsz <2 x float> %a, %y 1190 ret <2 x float> %r 1191} 1192 1193; Negative test - negated operand needed. 1194; Y - (Y + X) --> -X 1195 1196define float @fadd_fsub_common_op_wrong_commute(float %x, float %y) { 1197; CHECK-LABEL: @fadd_fsub_common_op_wrong_commute( 1198; CHECK-NEXT: [[A:%.*]] = fadd float [[Y:%.*]], [[X:%.*]] 1199; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz float [[Y]], [[A]] 1200; CHECK-NEXT: ret float [[R]] 1201; 1202 %a = fadd float %y, %x 1203 %r = fsub reassoc nsz float %y, %a 1204 ret float %r 1205} 1206 1207; Negative test - negated operand needed. 1208; Y - (X + Y) --> -X 1209 1210define float @fadd_fsub_common_op_wrong_commute_commute(float %x, float %y) { 1211; CHECK-LABEL: @fadd_fsub_common_op_wrong_commute_commute( 1212; CHECK-NEXT: [[A:%.*]] = fadd float [[X:%.*]], [[Y:%.*]] 1213; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz float [[Y]], [[A]] 1214; CHECK-NEXT: ret float [[R]] 1215; 1216 %a = fadd float %x, %y 1217 %r = fsub reassoc nsz float %y, %a 1218 ret float %r 1219} 1220 1221; Y + (X - Y) --> X 1222 1223define <2 x float> @fsub_fadd_common_op_vec(<2 x float> %x, <2 x float> %y) { 1224; CHECK-LABEL: @fsub_fadd_common_op_vec( 1225; CHECK-NEXT: ret <2 x float> [[X:%.*]] 1226; 1227 %s = fsub <2 x float> %x, %y 1228 %r = fadd reassoc nsz <2 x float> %y, %s 1229 ret <2 x float> %r 1230} 1231 1232; (X - Y) + Y --> X 1233 1234define float @fsub_fadd_common_op_commute(float %x, float %y) { 1235; CHECK-LABEL: @fsub_fadd_common_op_commute( 1236; CHECK-NEXT: ret float [[X:%.*]] 1237; 1238 %s = fsub float %x, %y 1239 %r = fadd reassoc nsz float %s, %y 1240 ret float %r 1241} 1242 1243; Negative test. 1244; Y + (Y - X) --> ? 1245 1246define float @fsub_fadd_common_op_wrong_commute(float %x, float %y) { 1247; CHECK-LABEL: @fsub_fadd_common_op_wrong_commute( 1248; CHECK-NEXT: [[S:%.*]] = fsub float [[Y:%.*]], [[X:%.*]] 1249; CHECK-NEXT: [[R:%.*]] = fadd reassoc nsz float [[Y]], [[S]] 1250; CHECK-NEXT: ret float [[R]] 1251; 1252 %s = fsub float %y, %x 1253 %r = fadd reassoc nsz float %y, %s 1254 ret float %r 1255} 1256 1257; Negative test. 1258; (Y - X) + Y --> ? 1259 1260define float @fsub_fadd_common_op_wrong_commute_commute(float %x, float %y) { 1261; CHECK-LABEL: @fsub_fadd_common_op_wrong_commute_commute( 1262; CHECK-NEXT: [[S:%.*]] = fsub float [[Y:%.*]], [[X:%.*]] 1263; CHECK-NEXT: [[R:%.*]] = fadd reassoc nsz float [[S]], [[Y]] 1264; CHECK-NEXT: ret float [[R]] 1265; 1266 %s = fsub float %y, %x 1267 %r = fadd reassoc nsz float %s, %y 1268 ret float %r 1269} 1270