1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -instcombine -S | FileCheck %s 3 4target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" 5target triple = "x86_64-unknown-linux-gnu" 6 7; Check for and against shrinkage when using the 8; unsafe-fp-math function attribute on a math lib 9; function. This optimization may be overridden by 10; the -enable-double-float-shrink option. 11; PR17850: http://llvm.org/bugs/show_bug.cgi?id=17850 12 13define float @acos_test1(float %f) { 14; CHECK-LABEL: @acos_test1( 15; CHECK-NEXT: [[ACOSF:%.*]] = call fast float @acosf(float [[F:%.*]]) 16; CHECK-NEXT: ret float [[ACOSF]] 17; 18 %conv = fpext float %f to double 19 %call = call fast double @acos(double %conv) 20 %conv1 = fptrunc double %call to float 21 ret float %conv1 22} 23 24define double @acos_test2(float %f) { 25; CHECK-LABEL: @acos_test2( 26; CHECK-NEXT: [[CONV:%.*]] = fpext float [[F:%.*]] to double 27; CHECK-NEXT: [[CALL:%.*]] = call fast double @acos(double [[CONV]]) 28; CHECK-NEXT: ret double [[CALL]] 29; 30 %conv = fpext float %f to double 31 %call = call fast double @acos(double %conv) 32 ret double %call 33} 34 35define float @acosh_test1(float %f) { 36; CHECK-LABEL: @acosh_test1( 37; CHECK-NEXT: [[ACOSHF:%.*]] = call fast float @acoshf(float [[F:%.*]]) 38; CHECK-NEXT: ret float [[ACOSHF]] 39; 40 %conv = fpext float %f to double 41 %call = call fast double @acosh(double %conv) 42 %conv1 = fptrunc double %call to float 43 ret float %conv1 44} 45 46define double @acosh_test2(float %f) { 47; CHECK-LABEL: @acosh_test2( 48; CHECK-NEXT: [[CONV:%.*]] = fpext float [[F:%.*]] to double 49; CHECK-NEXT: [[CALL:%.*]] = call fast double @acosh(double [[CONV]]) 50; CHECK-NEXT: ret double [[CALL]] 51; 52 %conv = fpext float %f to double 53 %call = call fast double @acosh(double %conv) 54 ret double %call 55} 56 57define float @asin_test1(float %f) { 58; CHECK-LABEL: @asin_test1( 59; CHECK-NEXT: [[ASINF:%.*]] = call fast float @asinf(float [[F:%.*]]) 60; CHECK-NEXT: ret float [[ASINF]] 61; 62 %conv = fpext float %f to double 63 %call = call fast double @asin(double %conv) 64 %conv1 = fptrunc double %call to float 65 ret float %conv1 66} 67 68define double @asin_test2(float %f) { 69; CHECK-LABEL: @asin_test2( 70; CHECK-NEXT: [[CONV:%.*]] = fpext float [[F:%.*]] to double 71; CHECK-NEXT: [[CALL:%.*]] = call fast double @asin(double [[CONV]]) 72; CHECK-NEXT: ret double [[CALL]] 73; 74 %conv = fpext float %f to double 75 %call = call fast double @asin(double %conv) 76 ret double %call 77} 78 79define float @asinh_test1(float %f) { 80; CHECK-LABEL: @asinh_test1( 81; CHECK-NEXT: [[ASINHF:%.*]] = call fast float @asinhf(float [[F:%.*]]) 82; CHECK-NEXT: ret float [[ASINHF]] 83; 84 %conv = fpext float %f to double 85 %call = call fast double @asinh(double %conv) 86 %conv1 = fptrunc double %call to float 87 ret float %conv1 88} 89 90define double @asinh_test2(float %f) { 91; CHECK-LABEL: @asinh_test2( 92; CHECK-NEXT: [[CONV:%.*]] = fpext float [[F:%.*]] to double 93; CHECK-NEXT: [[CALL:%.*]] = call fast double @asinh(double [[CONV]]) 94; CHECK-NEXT: ret double [[CALL]] 95; 96 %conv = fpext float %f to double 97 %call = call fast double @asinh(double %conv) 98 ret double %call 99} 100 101define float @atan_test1(float %f) { 102; CHECK-LABEL: @atan_test1( 103; CHECK-NEXT: [[ATANF:%.*]] = call fast float @atanf(float [[F:%.*]]) 104; CHECK-NEXT: ret float [[ATANF]] 105; 106 %conv = fpext float %f to double 107 %call = call fast double @atan(double %conv) 108 %conv1 = fptrunc double %call to float 109 ret float %conv1 110} 111 112define double @atan_test2(float %f) { 113; CHECK-LABEL: @atan_test2( 114; CHECK-NEXT: [[CONV:%.*]] = fpext float [[F:%.*]] to double 115; CHECK-NEXT: [[CALL:%.*]] = call fast double @atan(double [[CONV]]) 116; CHECK-NEXT: ret double [[CALL]] 117; 118 %conv = fpext float %f to double 119 %call = call fast double @atan(double %conv) 120 ret double %call 121} 122 123define float @atanh_test1(float %f) { 124; CHECK-LABEL: @atanh_test1( 125; CHECK-NEXT: [[ATANHF:%.*]] = call fast float @atanhf(float [[F:%.*]]) 126; CHECK-NEXT: ret float [[ATANHF]] 127; 128 %conv = fpext float %f to double 129 %call = call fast double @atanh(double %conv) 130 %conv1 = fptrunc double %call to float 131 ret float %conv1 132} 133 134define double @atanh_test2(float %f) { 135; CHECK-LABEL: @atanh_test2( 136; CHECK-NEXT: [[CONV:%.*]] = fpext float [[F:%.*]] to double 137; CHECK-NEXT: [[CALL:%.*]] = call fast double @atanh(double [[CONV]]) 138; CHECK-NEXT: ret double [[CALL]] 139; 140 %conv = fpext float %f to double 141 %call = call fast double @atanh(double %conv) 142 ret double %call 143} 144 145define float @cbrt_test1(float %f) { 146; CHECK-LABEL: @cbrt_test1( 147; CHECK-NEXT: [[CBRTF:%.*]] = call fast float @cbrtf(float [[F:%.*]]) 148; CHECK-NEXT: ret float [[CBRTF]] 149; 150 %conv = fpext float %f to double 151 %call = call fast double @cbrt(double %conv) 152 %conv1 = fptrunc double %call to float 153 ret float %conv1 154} 155 156define double @cbrt_test2(float %f) { 157; CHECK-LABEL: @cbrt_test2( 158; CHECK-NEXT: [[CONV:%.*]] = fpext float [[F:%.*]] to double 159; CHECK-NEXT: [[CALL:%.*]] = call fast double @cbrt(double [[CONV]]) 160; CHECK-NEXT: ret double [[CALL]] 161; 162 %conv = fpext float %f to double 163 %call = call fast double @cbrt(double %conv) 164 ret double %call 165} 166 167define float @exp_test1(float %f) { 168; CHECK-LABEL: @exp_test1( 169; CHECK-NEXT: [[EXPF:%.*]] = call fast float @expf(float [[F:%.*]]) 170; CHECK-NEXT: ret float [[EXPF]] 171; 172 %conv = fpext float %f to double 173 %call = call fast double @exp(double %conv) 174 %conv1 = fptrunc double %call to float 175 ret float %conv1 176} 177 178define double @exp_test2(float %f) { 179; CHECK-LABEL: @exp_test2( 180; CHECK-NEXT: [[CONV:%.*]] = fpext float [[F:%.*]] to double 181; CHECK-NEXT: [[CALL:%.*]] = call fast double @exp(double [[CONV]]) 182; CHECK-NEXT: ret double [[CALL]] 183; 184 %conv = fpext float %f to double 185 %call = call fast double @exp(double %conv) 186 ret double %call 187} 188 189define float @expm1_test1(float %f) { 190; CHECK-LABEL: @expm1_test1( 191; CHECK-NEXT: [[EXPM1F:%.*]] = call fast float @expm1f(float [[F:%.*]]) 192; CHECK-NEXT: ret float [[EXPM1F]] 193; 194 %conv = fpext float %f to double 195 %call = call fast double @expm1(double %conv) 196 %conv1 = fptrunc double %call to float 197 ret float %conv1 198} 199 200define double @expm1_test2(float %f) { 201; CHECK-LABEL: @expm1_test2( 202; CHECK-NEXT: [[CONV:%.*]] = fpext float [[F:%.*]] to double 203; CHECK-NEXT: [[CALL:%.*]] = call fast double @expm1(double [[CONV]]) 204; CHECK-NEXT: ret double [[CALL]] 205; 206 %conv = fpext float %f to double 207 %call = call fast double @expm1(double %conv) 208 ret double %call 209} 210 211; exp10f() doesn't exist for this triple, so it doesn't shrink. 212 213define float @exp10_test1(float %f) { 214; CHECK-LABEL: @exp10_test1( 215; CHECK-NEXT: [[CONV:%.*]] = fpext float [[F:%.*]] to double 216; CHECK-NEXT: [[CALL:%.*]] = call fast double @exp10(double [[CONV]]) 217; CHECK-NEXT: [[CONV1:%.*]] = fptrunc double [[CALL]] to float 218; CHECK-NEXT: ret float [[CONV1]] 219; 220 %conv = fpext float %f to double 221 %call = call fast double @exp10(double %conv) 222 %conv1 = fptrunc double %call to float 223 ret float %conv1 224} 225 226define double @exp10_test2(float %f) { 227; CHECK-LABEL: @exp10_test2( 228; CHECK-NEXT: [[CONV:%.*]] = fpext float [[F:%.*]] to double 229; CHECK-NEXT: [[CALL:%.*]] = call fast double @exp10(double [[CONV]]) 230; CHECK-NEXT: ret double [[CALL]] 231; 232 %conv = fpext float %f to double 233 %call = call fast double @exp10(double %conv) 234 ret double %call 235} 236 237define float @log_test1(float %f) { 238; CHECK-LABEL: @log_test1( 239; CHECK-NEXT: [[LOGF:%.*]] = call fast float @logf(float [[F:%.*]]) 240; CHECK-NEXT: ret float [[LOGF]] 241; 242 %conv = fpext float %f to double 243 %call = call fast double @log(double %conv) 244 %conv1 = fptrunc double %call to float 245 ret float %conv1 246} 247 248define double @log_test2(float %f) { 249; CHECK-LABEL: @log_test2( 250; CHECK-NEXT: [[CONV:%.*]] = fpext float [[F:%.*]] to double 251; CHECK-NEXT: [[CALL:%.*]] = call fast double @log(double [[CONV]]) 252; CHECK-NEXT: ret double [[CALL]] 253; 254 %conv = fpext float %f to double 255 %call = call fast double @log(double %conv) 256 ret double %call 257} 258 259define float @log10_test1(float %f) { 260; CHECK-LABEL: @log10_test1( 261; CHECK-NEXT: [[LOG10F:%.*]] = call fast float @log10f(float [[F:%.*]]) 262; CHECK-NEXT: ret float [[LOG10F]] 263; 264 %conv = fpext float %f to double 265 %call = call fast double @log10(double %conv) 266 %conv1 = fptrunc double %call to float 267 ret float %conv1 268} 269 270define double @log10_test2(float %f) { 271; CHECK-LABEL: @log10_test2( 272; CHECK-NEXT: [[CONV:%.*]] = fpext float [[F:%.*]] to double 273; CHECK-NEXT: [[CALL:%.*]] = call fast double @log10(double [[CONV]]) 274; CHECK-NEXT: ret double [[CALL]] 275; 276 %conv = fpext float %f to double 277 %call = call fast double @log10(double %conv) 278 ret double %call 279} 280 281define float @log1p_test1(float %f) { 282; CHECK-LABEL: @log1p_test1( 283; CHECK-NEXT: [[LOG1PF:%.*]] = call fast float @log1pf(float [[F:%.*]]) 284; CHECK-NEXT: ret float [[LOG1PF]] 285; 286 %conv = fpext float %f to double 287 %call = call fast double @log1p(double %conv) 288 %conv1 = fptrunc double %call to float 289 ret float %conv1 290} 291 292define double @log1p_test2(float %f) { 293; CHECK-LABEL: @log1p_test2( 294; CHECK-NEXT: [[CONV:%.*]] = fpext float [[F:%.*]] to double 295; CHECK-NEXT: [[CALL:%.*]] = call fast double @log1p(double [[CONV]]) 296; CHECK-NEXT: ret double [[CALL]] 297; 298 %conv = fpext float %f to double 299 %call = call fast double @log1p(double %conv) 300 ret double %call 301} 302 303define float @log2_test1(float %f) { 304; CHECK-LABEL: @log2_test1( 305; CHECK-NEXT: [[LOG2F:%.*]] = call fast float @log2f(float [[F:%.*]]) 306; CHECK-NEXT: ret float [[LOG2F]] 307; 308 %conv = fpext float %f to double 309 %call = call fast double @log2(double %conv) 310 %conv1 = fptrunc double %call to float 311 ret float %conv1 312} 313 314define double @log2_test2(float %f) { 315; CHECK-LABEL: @log2_test2( 316; CHECK-NEXT: [[CONV:%.*]] = fpext float [[F:%.*]] to double 317; CHECK-NEXT: [[CALL:%.*]] = call fast double @log2(double [[CONV]]) 318; CHECK-NEXT: ret double [[CALL]] 319; 320 %conv = fpext float %f to double 321 %call = call fast double @log2(double %conv) 322 ret double %call 323} 324 325define float @logb_test1(float %f) { 326; CHECK-LABEL: @logb_test1( 327; CHECK-NEXT: [[LOGBF:%.*]] = call fast float @logbf(float [[F:%.*]]) 328; CHECK-NEXT: ret float [[LOGBF]] 329; 330 %conv = fpext float %f to double 331 %call = call fast double @logb(double %conv) 332 %conv1 = fptrunc double %call to float 333 ret float %conv1 334} 335 336define double @logb_test2(float %f) { 337; CHECK-LABEL: @logb_test2( 338; CHECK-NEXT: [[CONV:%.*]] = fpext float [[F:%.*]] to double 339; CHECK-NEXT: [[CALL:%.*]] = call fast double @logb(double [[CONV]]) 340; CHECK-NEXT: ret double [[CALL]] 341; 342 %conv = fpext float %f to double 343 %call = call fast double @logb(double %conv) 344 ret double %call 345} 346 347; FIXME: Miscompile - we dropped the 2nd argument! 348 349define float @pow_test1(float %f, float %g) { 350; CHECK-LABEL: @pow_test1( 351; CHECK-NEXT: [[POWF:%.*]] = call fast float @powf(float [[F:%.*]]) 352; CHECK-NEXT: ret float [[POWF]] 353; 354 %df = fpext float %f to double 355 %dg = fpext float %g to double 356 %call = call fast double @pow(double %df, double %dg) 357 %fr = fptrunc double %call to float 358 ret float %fr 359} 360 361; TODO: This should shrink? 362 363define double @pow_test2(float %f, float %g) { 364; CHECK-LABEL: @pow_test2( 365; CHECK-NEXT: [[DF:%.*]] = fpext float [[F:%.*]] to double 366; CHECK-NEXT: [[DG:%.*]] = fpext float [[G:%.*]] to double 367; CHECK-NEXT: [[CALL:%.*]] = call fast double @pow(double [[DF]], double [[DG]]) 368; CHECK-NEXT: ret double [[CALL]] 369; 370 %df = fpext float %f to double 371 %dg = fpext float %g to double 372 %call = call fast double @pow(double %df, double %dg) 373 ret double %call 374} 375 376define float @sin_test1(float %f) { 377; CHECK-LABEL: @sin_test1( 378; CHECK-NEXT: [[SINF:%.*]] = call fast float @sinf(float [[F:%.*]]) 379; CHECK-NEXT: ret float [[SINF]] 380; 381 %conv = fpext float %f to double 382 %call = call fast double @sin(double %conv) 383 %conv1 = fptrunc double %call to float 384 ret float %conv1 385} 386 387define double @sin_test2(float %f) { 388; CHECK-LABEL: @sin_test2( 389; CHECK-NEXT: [[CONV:%.*]] = fpext float [[F:%.*]] to double 390; CHECK-NEXT: [[CALL:%.*]] = call fast double @sin(double [[CONV]]) 391; CHECK-NEXT: ret double [[CALL]] 392; 393 %conv = fpext float %f to double 394 %call = call fast double @sin(double %conv) 395 ret double %call 396} 397 398define float @sqrt_test1(float %f) { 399; CHECK-LABEL: @sqrt_test1( 400; CHECK-NEXT: [[SQRTF:%.*]] = call float @sqrtf(float [[F:%.*]]) 401; CHECK-NEXT: ret float [[SQRTF]] 402; 403 %conv = fpext float %f to double 404 %call = call double @sqrt(double %conv) 405 %conv1 = fptrunc double %call to float 406 ret float %conv1 407} 408 409define double @sqrt_test2(float %f) { 410; CHECK-LABEL: @sqrt_test2( 411; CHECK-NEXT: [[CONV:%.*]] = fpext float [[F:%.*]] to double 412; CHECK-NEXT: [[CALL:%.*]] = call double @sqrt(double [[CONV]]) 413; CHECK-NEXT: ret double [[CALL]] 414; 415 %conv = fpext float %f to double 416 %call = call double @sqrt(double %conv) 417 ret double %call 418} 419 420define float @sqrt_int_test1(float %f) { 421; CHECK-LABEL: @sqrt_int_test1( 422; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.sqrt.f32(float [[F:%.*]]) 423; CHECK-NEXT: ret float [[TMP1]] 424; 425 %conv = fpext float %f to double 426 %call = call double @llvm.sqrt.f64(double %conv) 427 %conv1 = fptrunc double %call to float 428 ret float %conv1 429} 430 431define double @sqrt_int_test2(float %f) { 432; CHECK-LABEL: @sqrt_int_test2( 433; CHECK-NEXT: [[CONV:%.*]] = fpext float [[F:%.*]] to double 434; CHECK-NEXT: [[CALL:%.*]] = call double @llvm.sqrt.f64(double [[CONV]]) 435; CHECK-NEXT: ret double [[CALL]] 436; 437 %conv = fpext float %f to double 438 %call = call double @llvm.sqrt.f64(double %conv) 439 ret double %call 440} 441 442define float @tan_test1(float %f) { 443; CHECK-LABEL: @tan_test1( 444; CHECK-NEXT: [[TANF:%.*]] = call fast float @tanf(float [[F:%.*]]) 445; CHECK-NEXT: ret float [[TANF]] 446; 447 %conv = fpext float %f to double 448 %call = call fast double @tan(double %conv) 449 %conv1 = fptrunc double %call to float 450 ret float %conv1 451} 452 453define double @tan_test2(float %f) { 454; CHECK-LABEL: @tan_test2( 455; CHECK-NEXT: [[CONV:%.*]] = fpext float [[F:%.*]] to double 456; CHECK-NEXT: [[CALL:%.*]] = call fast double @tan(double [[CONV]]) 457; CHECK-NEXT: ret double [[CALL]] 458; 459 %conv = fpext float %f to double 460 %call = call fast double @tan(double %conv) 461 ret double %call 462} 463define float @tanh_test1(float %f) { 464; CHECK-LABEL: @tanh_test1( 465; CHECK-NEXT: [[TANHF:%.*]] = call fast float @tanhf(float [[F:%.*]]) 466; CHECK-NEXT: ret float [[TANHF]] 467; 468 %conv = fpext float %f to double 469 %call = call fast double @tanh(double %conv) 470 %conv1 = fptrunc double %call to float 471 ret float %conv1 472} 473 474define double @tanh_test2(float %f) { 475; CHECK-LABEL: @tanh_test2( 476; CHECK-NEXT: [[CONV:%.*]] = fpext float [[F:%.*]] to double 477; CHECK-NEXT: [[CALL:%.*]] = call fast double @tanh(double [[CONV]]) 478; CHECK-NEXT: ret double [[CALL]] 479; 480 %conv = fpext float %f to double 481 %call = call fast double @tanh(double %conv) 482 ret double %call 483} 484 485; 'arcp' on an fmax() is meaningless. This test just proves that 486; flags are propagated for shrunken *binary* double FP calls. 487define float @max1(float %a, float %b) { 488; CHECK-LABEL: @max1( 489; CHECK-NEXT: [[FMAXF:%.*]] = call arcp float @fmaxf(float [[A:%.*]], float [[B:%.*]]) 490; CHECK-NEXT: ret float [[FMAXF]] 491; 492 %c = fpext float %a to double 493 %d = fpext float %b to double 494 %e = call arcp double @fmax(double %c, double %d) 495 %f = fptrunc double %e to float 496 ret float %f 497} 498 499; A function can have a name that matches a common libcall, 500; but with the wrong type(s). Let it be. 501 502define float @fake_fmin(float %a, float %b) { 503; CHECK-LABEL: @fake_fmin( 504; CHECK-NEXT: [[C:%.*]] = fpext float [[A:%.*]] to fp128 505; CHECK-NEXT: [[D:%.*]] = fpext float [[B:%.*]] to fp128 506; CHECK-NEXT: [[E:%.*]] = call fp128 @fmin(fp128 [[C]], fp128 [[D]]) 507; CHECK-NEXT: [[F:%.*]] = fptrunc fp128 [[E]] to float 508; CHECK-NEXT: ret float [[F]] 509; 510 %c = fpext float %a to fp128 511 %d = fpext float %b to fp128 512 %e = call fp128 @fmin(fp128 %c, fp128 %d) 513 %f = fptrunc fp128 %e to float 514 ret float %f 515} 516 517declare fp128 @fmin(fp128, fp128) ; This is not the 'fmin' you're looking for. 518 519declare double @fmax(double, double) 520 521declare double @tanh(double) 522declare double @tan(double) 523 524; sqrt is a special case: the shrinking optimization 525; is valid even without unsafe-fp-math. 526declare double @sqrt(double) 527declare double @llvm.sqrt.f64(double) 528 529declare double @sin(double) 530declare double @pow(double, double) 531declare double @log2(double) 532declare double @log1p(double) 533declare double @log10(double) 534declare double @log(double) 535declare double @logb(double) 536declare double @exp10(double) 537declare double @expm1(double) 538declare double @exp(double) 539declare double @cbrt(double) 540declare double @atanh(double) 541declare double @atan(double) 542declare double @acos(double) 543declare double @acosh(double) 544declare double @asin(double) 545declare double @asinh(double) 546 547