1 ; RUN: opt < %s -instcombine -S | FileCheck %s 2 3 target 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" 4 target triple = "x86_64-unknown-linux-gnu" 5 6 ; Check for and against shrinkage when using the 7 ; unsafe-fp-math function attribute on a math lib 8 ; function. This optimization may be overridden by 9 ; the -enable-double-float-shrink option. 10 ; PR17850: http://llvm.org/bugs/show_bug.cgi?id=17850 11 12 define float @acos_test1(float %f) { 13 %conv = fpext float %f to double 14 %call = call fast double @acos(double %conv) 15 %conv1 = fptrunc double %call to float 16 ret float %conv1 17 ; CHECK-LABEL: acos_test1 18 ; CHECK: call fast float @acosf(float %f) 19 } 20 21 define double @acos_test2(float %f) { 22 %conv = fpext float %f to double 23 %call = call fast double @acos(double %conv) 24 ret double %call 25 ; CHECK-LABEL: acos_test2 26 ; CHECK: call fast double @acos(double %conv) 27 } 28 29 define float @acosh_test1(float %f) { 30 %conv = fpext float %f to double 31 %call = call fast double @acosh(double %conv) 32 %conv1 = fptrunc double %call to float 33 ret float %conv1 34 ; CHECK-LABEL: acosh_test1 35 ; CHECK: call fast float @acoshf(float %f) 36 } 37 38 define double @acosh_test2(float %f) { 39 %conv = fpext float %f to double 40 %call = call fast double @acosh(double %conv) 41 ret double %call 42 ; CHECK-LABEL: acosh_test2 43 ; CHECK: call fast double @acosh(double %conv) 44 } 45 46 define float @asin_test1(float %f) { 47 %conv = fpext float %f to double 48 %call = call fast double @asin(double %conv) 49 %conv1 = fptrunc double %call to float 50 ret float %conv1 51 ; CHECK-LABEL: asin_test1 52 ; CHECK: call fast float @asinf(float %f) 53 } 54 55 define double @asin_test2(float %f) { 56 %conv = fpext float %f to double 57 %call = call fast double @asin(double %conv) 58 ret double %call 59 ; CHECK-LABEL: asin_test2 60 ; CHECK: call fast double @asin(double %conv) 61 } 62 63 define float @asinh_test1(float %f) { 64 %conv = fpext float %f to double 65 %call = call fast double @asinh(double %conv) 66 %conv1 = fptrunc double %call to float 67 ret float %conv1 68 ; CHECK-LABEL: asinh_test1 69 ; CHECK: call fast float @asinhf(float %f) 70 } 71 72 define double @asinh_test2(float %f) { 73 %conv = fpext float %f to double 74 %call = call fast double @asinh(double %conv) 75 ret double %call 76 ; CHECK-LABEL: asinh_test2 77 ; CHECK: call fast double @asinh(double %conv) 78 } 79 80 define float @atan_test1(float %f) { 81 %conv = fpext float %f to double 82 %call = call fast double @atan(double %conv) 83 %conv1 = fptrunc double %call to float 84 ret float %conv1 85 ; CHECK-LABEL: atan_test1 86 ; CHECK: call fast float @atanf(float %f) 87 } 88 89 define double @atan_test2(float %f) { 90 %conv = fpext float %f to double 91 %call = call fast double @atan(double %conv) 92 ret double %call 93 ; CHECK-LABEL: atan_test2 94 ; CHECK: call fast double @atan(double %conv) 95 } 96 97 define float @atanh_test1(float %f) { 98 %conv = fpext float %f to double 99 %call = call fast double @atanh(double %conv) 100 %conv1 = fptrunc double %call to float 101 ret float %conv1 102 ; CHECK-LABEL: atanh_test1 103 ; CHECK: call fast float @atanhf(float %f) 104 } 105 106 define double @atanh_test2(float %f) { 107 %conv = fpext float %f to double 108 %call = call fast double @atanh(double %conv) 109 ret double %call 110 ; CHECK-LABEL: atanh_test2 111 ; CHECK: call fast double @atanh(double %conv) 112 } 113 114 define float @cbrt_test1(float %f) { 115 %conv = fpext float %f to double 116 %call = call fast double @cbrt(double %conv) 117 %conv1 = fptrunc double %call to float 118 ret float %conv1 119 ; CHECK-LABEL: cbrt_test1 120 ; CHECK: call fast float @cbrtf(float %f) 121 } 122 123 define double @cbrt_test2(float %f) { 124 %conv = fpext float %f to double 125 %call = call fast double @cbrt(double %conv) 126 ret double %call 127 ; CHECK-LABEL: cbrt_test2 128 ; CHECK: call fast double @cbrt(double %conv) 129 } 130 131 define float @exp_test1(float %f) { 132 %conv = fpext float %f to double 133 %call = call fast double @exp(double %conv) 134 %conv1 = fptrunc double %call to float 135 ret float %conv1 136 ; CHECK-LABEL: exp_test1 137 ; CHECK: call fast float @expf(float %f) 138 } 139 140 define double @exp_test2(float %f) { 141 %conv = fpext float %f to double 142 %call = call fast double @exp(double %conv) 143 ret double %call 144 ; CHECK-LABEL: exp_test2 145 ; CHECK: call fast double @exp(double %conv) 146 } 147 148 define float @expm1_test1(float %f) { 149 %conv = fpext float %f to double 150 %call = call fast double @expm1(double %conv) 151 %conv1 = fptrunc double %call to float 152 ret float %conv1 153 ; CHECK-LABEL: expm1_test1 154 ; CHECK: call fast float @expm1f(float %f) 155 } 156 157 define double @expm1_test2(float %f) { 158 %conv = fpext float %f to double 159 %call = call fast double @expm1(double %conv) 160 ret double %call 161 ; CHECK-LABEL: expm1_test2 162 ; CHECK: call fast double @expm1(double %conv) 163 } 164 165 ; exp10f() doesn't exist for this triple, so it doesn't shrink. 166 167 define float @exp10_test1(float %f) { 168 %conv = fpext float %f to double 169 %call = call fast double @exp10(double %conv) 170 %conv1 = fptrunc double %call to float 171 ret float %conv1 172 ; CHECK-LABEL: exp10_test1 173 ; CHECK: call fast double @exp10(double %conv) 174 } 175 176 define double @exp10_test2(float %f) { 177 %conv = fpext float %f to double 178 %call = call fast double @exp10(double %conv) 179 ret double %call 180 ; CHECK-LABEL: exp10_test2 181 ; CHECK: call fast double @exp10(double %conv) 182 } 183 184 define float @log_test1(float %f) { 185 %conv = fpext float %f to double 186 %call = call fast double @log(double %conv) 187 %conv1 = fptrunc double %call to float 188 ret float %conv1 189 ; CHECK-LABEL: log_test1 190 ; CHECK: call fast float @logf(float %f) 191 } 192 193 define double @log_test2(float %f) { 194 %conv = fpext float %f to double 195 %call = call fast double @log(double %conv) 196 ret double %call 197 ; CHECK-LABEL: log_test2 198 ; CHECK: call fast double @log(double %conv) 199 } 200 201 define float @log10_test1(float %f) { 202 %conv = fpext float %f to double 203 %call = call fast double @log10(double %conv) 204 %conv1 = fptrunc double %call to float 205 ret float %conv1 206 ; CHECK-LABEL: log10_test1 207 ; CHECK: call fast float @log10f(float %f) 208 } 209 210 define double @log10_test2(float %f) { 211 %conv = fpext float %f to double 212 %call = call fast double @log10(double %conv) 213 ret double %call 214 ; CHECK-LABEL: log10_test2 215 ; CHECK: call fast double @log10(double %conv) 216 } 217 218 define float @log1p_test1(float %f) { 219 %conv = fpext float %f to double 220 %call = call fast double @log1p(double %conv) 221 %conv1 = fptrunc double %call to float 222 ret float %conv1 223 ; CHECK-LABEL: log1p_test1 224 ; CHECK: call fast float @log1pf(float %f) 225 } 226 227 define double @log1p_test2(float %f) { 228 %conv = fpext float %f to double 229 %call = call fast double @log1p(double %conv) 230 ret double %call 231 ; CHECK-LABEL: log1p_test2 232 ; CHECK: call fast double @log1p(double %conv) 233 } 234 235 define float @log2_test1(float %f) { 236 %conv = fpext float %f to double 237 %call = call fast double @log2(double %conv) 238 %conv1 = fptrunc double %call to float 239 ret float %conv1 240 ; CHECK-LABEL: log2_test1 241 ; CHECK: call fast float @log2f(float %f) 242 } 243 244 define double @log2_test2(float %f) { 245 %conv = fpext float %f to double 246 %call = call fast double @log2(double %conv) 247 ret double %call 248 ; CHECK-LABEL: log2_test2 249 ; CHECK: call fast double @log2(double %conv) 250 } 251 252 define float @logb_test1(float %f) { 253 %conv = fpext float %f to double 254 %call = call fast double @logb(double %conv) 255 %conv1 = fptrunc double %call to float 256 ret float %conv1 257 ; CHECK-LABEL: logb_test1 258 ; CHECK: call fast float @logbf(float %f) 259 } 260 261 define double @logb_test2(float %f) { 262 %conv = fpext float %f to double 263 %call = call fast double @logb(double %conv) 264 ret double %call 265 ; CHECK-LABEL: logb_test2 266 ; CHECK: call fast double @logb(double %conv) 267 } 268 269 define float @sin_test1(float %f) { 270 %conv = fpext float %f to double 271 %call = call fast double @sin(double %conv) 272 %conv1 = fptrunc double %call to float 273 ret float %conv1 274 ; CHECK-LABEL: sin_test1 275 ; CHECK: call fast float @sinf(float %f) 276 } 277 278 define double @sin_test2(float %f) { 279 %conv = fpext float %f to double 280 %call = call fast double @sin(double %conv) 281 ret double %call 282 ; CHECK-LABEL: sin_test2 283 ; CHECK: call fast double @sin(double %conv) 284 } 285 286 define float @sqrt_test1(float %f) { 287 %conv = fpext float %f to double 288 %call = call double @sqrt(double %conv) 289 %conv1 = fptrunc double %call to float 290 ret float %conv1 291 ; CHECK-LABEL: sqrt_test1 292 ; CHECK: call float @sqrtf(float %f) 293 } 294 295 define double @sqrt_test2(float %f) { 296 %conv = fpext float %f to double 297 %call = call double @sqrt(double %conv) 298 ret double %call 299 ; CHECK-LABEL: sqrt_test2 300 ; CHECK: call double @sqrt(double %conv) 301 } 302 303 define float @sqrt_int_test1(float %f) { 304 %conv = fpext float %f to double 305 %call = call double @llvm.sqrt.f64(double %conv) 306 %conv1 = fptrunc double %call to float 307 ret float %conv1 308 ; CHECK-LABEL: sqrt_int_test1 309 ; CHECK: call float @llvm.sqrt.f32(float %f) 310 } 311 312 define double @sqrt_int_test2(float %f) { 313 %conv = fpext float %f to double 314 %call = call double @llvm.sqrt.f64(double %conv) 315 ret double %call 316 ; CHECK-LABEL: sqrt_int_test2 317 ; CHECK: call double @llvm.sqrt.f64(double %conv) 318 } 319 320 define float @tan_test1(float %f) { 321 %conv = fpext float %f to double 322 %call = call fast double @tan(double %conv) 323 %conv1 = fptrunc double %call to float 324 ret float %conv1 325 ; CHECK-LABEL: tan_test1 326 ; CHECK: call fast float @tanf(float %f) 327 } 328 329 define double @tan_test2(float %f) { 330 %conv = fpext float %f to double 331 %call = call fast double @tan(double %conv) 332 ret double %call 333 ; CHECK-LABEL: tan_test2 334 ; CHECK: call fast double @tan(double %conv) 335 } 336 define float @tanh_test1(float %f) { 337 %conv = fpext float %f to double 338 %call = call fast double @tanh(double %conv) 339 %conv1 = fptrunc double %call to float 340 ret float %conv1 341 ; CHECK-LABEL: tanh_test1 342 ; CHECK: call fast float @tanhf(float %f) 343 } 344 345 define double @tanh_test2(float %f) { 346 %conv = fpext float %f to double 347 %call = call fast double @tanh(double %conv) 348 ret double %call 349 ; CHECK-LABEL: tanh_test2 350 ; CHECK: call fast double @tanh(double %conv) 351 } 352 353 ; 'arcp' on an fmax() is meaningless. This test just proves that 354 ; flags are propagated for shrunken *binary* double FP calls. 355 define float @max1(float %a, float %b) { 356 %c = fpext float %a to double 357 %d = fpext float %b to double 358 %e = call arcp double @fmax(double %c, double %d) 359 %f = fptrunc double %e to float 360 ret float %f 361 362 ; CHECK-LABEL: max1( 363 ; CHECK-NEXT: call arcp float @fmaxf(float %a, float %b) 364 ; CHECK-NEXT: ret 365 } 366 367 ; A function can have a name that matches a common libcall, 368 ; but with the wrong type(s). Let it be. 369 370 define float @fake_fmin(float %a, float %b) { 371 %c = fpext float %a to fp128 372 %d = fpext float %b to fp128 373 %e = call fp128 @fmin(fp128 %c, fp128 %d) 374 %f = fptrunc fp128 %e to float 375 ret float %f 376 377 ; CHECK-LABEL: fake_fmin( 378 ; CHECK-NEXT: %c = fpext float %a to fp128 379 ; CHECK-NEXT: %d = fpext float %b to fp128 380 ; CHECK-NEXT: %e = call fp128 @fmin(fp128 %c, fp128 %d) 381 ; CHECK-NEXT: %f = fptrunc fp128 %e to float 382 ; CHECK-NEXT: ret float %f 383 } 384 385 declare fp128 @fmin(fp128, fp128) ; This is not the 'fmin' you're looking for. 386 387 declare double @fmax(double, double) 388 389 declare double @tanh(double) 390 declare double @tan(double) 391 392 ; sqrt is a special case: the shrinking optimization 393 ; is valid even without unsafe-fp-math. 394 declare double @sqrt(double) 395 declare double @llvm.sqrt.f64(double) 396 397 declare double @sin(double) 398 declare double @log2(double) 399 declare double @log1p(double) 400 declare double @log10(double) 401 declare double @log(double) 402 declare double @logb(double) 403 declare double @exp10(double) 404 declare double @expm1(double) 405 declare double @exp(double) 406 declare double @cbrt(double) 407 declare double @atanh(double) 408 declare double @atan(double) 409 declare double @acos(double) 410 declare double @acosh(double) 411 declare double @asin(double) 412 declare double @asinh(double) 413 414