1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s --check-prefixes=ANY,NO-FLOAT-SHRINK 3; RUN: opt < %s -passes=instcombine -enable-double-float-shrink -S | FileCheck %s --check-prefixes=ANY,DO-FLOAT-SHRINK 4 5target 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" 6 7declare double @cos(double) 8declare double @llvm.cos.f64(double) 9declare float @cosf(float) 10declare float @llvm.cos.f32(float) 11 12declare double @sin(double) 13declare double @llvm.sin.f64(double) 14declare float @sinf(float) 15declare float @llvm.sin.f32(float) 16 17declare double @tan(double) 18declare fp128 @tanl(fp128) 19 20declare double @fabs(double) 21declare double @llvm.fabs.f64(double) 22declare float @fabsf(float) 23declare float @llvm.fabs.f32(float) 24 25declare double @llvm.copysign(double, double) 26declare float @llvm.copysign.f32(float, float) 27 28; cos(-x) -> cos(x); 29 30define double @cos_negated_arg(double %x) { 31; ANY-LABEL: @cos_negated_arg( 32; ANY-NEXT: [[COS:%.*]] = call double @cos(double [[X:%.*]]) 33; ANY-NEXT: ret double [[COS]] 34; 35 %neg = fsub double -0.0, %x 36 %r = call double @cos(double %neg) 37 ret double %r 38} 39 40define double @cos_negated_arg_tail(double %x) { 41; ANY-LABEL: @cos_negated_arg_tail( 42; ANY-NEXT: [[COS:%.*]] = tail call double @cos(double [[X:%.*]]) 43; ANY-NEXT: ret double [[COS]] 44; 45 %neg = fsub double -0.0, %x 46 %r = tail call double @cos(double %neg) 47 ret double %r 48} 49 50define double @cos_negated_arg_musttail(double %x) { 51; ANY-LABEL: @cos_negated_arg_musttail( 52; ANY-NEXT: [[NEG:%.*]] = fneg double [[X:%.*]] 53; ANY-NEXT: [[R:%.*]] = musttail call double @cos(double [[NEG]]) 54; ANY-NEXT: ret double [[R]] 55; 56 %neg = fsub double -0.0, %x 57 %r = musttail call double @cos(double %neg) 58 ret double %r 59} 60 61define double @cos_unary_negated_arg(double %x) { 62; ANY-LABEL: @cos_unary_negated_arg( 63; ANY-NEXT: [[COS:%.*]] = call double @cos(double [[X:%.*]]) 64; ANY-NEXT: ret double [[COS]] 65; 66 %neg = fneg double %x 67 %r = call double @cos(double %neg) 68 ret double %r 69} 70 71define float @cosf_negated_arg(float %x) { 72; ANY-LABEL: @cosf_negated_arg( 73; ANY-NEXT: [[COS:%.*]] = call float @cosf(float [[X:%.*]]) 74; ANY-NEXT: ret float [[COS]] 75; 76 %neg = fsub float -0.0, %x 77 %r = call float @cosf(float %neg) 78 ret float %r 79} 80 81define float @cosf_unary_negated_arg(float %x) { 82; ANY-LABEL: @cosf_unary_negated_arg( 83; ANY-NEXT: [[COS:%.*]] = call float @cosf(float [[X:%.*]]) 84; ANY-NEXT: ret float [[COS]] 85; 86 %neg = fneg float %x 87 %r = call float @cosf(float %neg) 88 ret float %r 89} 90 91define float @cosf_negated_arg_FMF(float %x) { 92; ANY-LABEL: @cosf_negated_arg_FMF( 93; ANY-NEXT: [[COS:%.*]] = call reassoc nnan float @cosf(float [[X:%.*]]) 94; ANY-NEXT: ret float [[COS]] 95; 96 %neg = fsub float -0.0, %x 97 %r = call nnan reassoc float @cosf(float %neg) 98 ret float %r 99} 100 101define float @cosf_unary_negated_arg_FMF(float %x) { 102; ANY-LABEL: @cosf_unary_negated_arg_FMF( 103; ANY-NEXT: [[COS:%.*]] = call reassoc nnan float @cosf(float [[X:%.*]]) 104; ANY-NEXT: ret float [[COS]] 105; 106 %neg = fneg float %x 107 %r = call nnan reassoc float @cosf(float %neg) 108 ret float %r 109} 110 111; cos(fabs(x)) -> cos(x) 112 113define double @cos_unary_fabs_arg(double %x) { 114; ANY-LABEL: @cos_unary_fabs_arg( 115; ANY-NEXT: [[COS:%.*]] = call double @cos(double [[X:%.*]]) 116; ANY-NEXT: ret double [[COS]] 117; 118 %fabs = tail call double @llvm.fabs.f64(double %x) 119 %r = call double @cos(double %fabs) 120 ret double %r 121} 122 123define float @cosf_unary_fabs_arg(float %x) { 124; ANY-LABEL: @cosf_unary_fabs_arg( 125; ANY-NEXT: [[COS:%.*]] = call float @cosf(float [[X:%.*]]) 126; ANY-NEXT: ret float [[COS]] 127; 128 %fabs = tail call float @llvm.fabs.f32(float %x) 129 %r = call float @cosf(float %fabs) 130 ret float %r 131} 132 133define float @cosf_unary_fabs_arg_FMF(float %x) { 134; ANY-LABEL: @cosf_unary_fabs_arg_FMF( 135; ANY-NEXT: [[COS:%.*]] = call reassoc nnan float @cosf(float [[X:%.*]]) 136; ANY-NEXT: ret float [[COS]] 137; 138 %fabs = tail call float @llvm.fabs.f32(float %x) 139 %r = call nnan reassoc float @cosf(float %fabs) 140 ret float %r 141} 142 143; cos(copysign(x, y)) -> cos(x) 144 145define double @cos_copysign_arg(double %x, double %y) { 146; ANY-LABEL: @cos_copysign_arg( 147; ANY-NEXT: [[COS:%.*]] = call double @cos(double [[X:%.*]]) 148; ANY-NEXT: ret double [[COS]] 149; 150 %copysign = tail call double @llvm.copysign(double %x, double %y) 151 %r = call double @cos(double %copysign) 152 ret double %r 153} 154 155 156define float @cosf_unary_copysign_arg(float %x) { 157; ANY-LABEL: @cosf_unary_copysign_arg( 158; ANY-NEXT: [[COS:%.*]] = call float @cosf(float [[X:%.*]]) 159; ANY-NEXT: ret float [[COS]] 160; 161 %copysign = tail call float @llvm.copysign.f32(float %x, float 1.0) 162 %r = call float @cosf(float %copysign) 163 ret float %r 164} 165 166define float @cosf_copysign_arg_FMF(float %x, float %y) { 167; ANY-LABEL: @cosf_copysign_arg_FMF( 168; ANY-NEXT: [[COS:%.*]] = call reassoc nnan float @cosf(float [[X:%.*]]) 169; ANY-NEXT: ret float [[COS]] 170; 171 %copysign = tail call float @llvm.copysign.f32(float %x, float %y) 172 %r = call nnan reassoc float @cosf(float %copysign) 173 ret float %r 174} 175 176; sin(-x) -> -sin(x); 177 178define double @sin_negated_arg(double %x) { 179; ANY-LABEL: @sin_negated_arg( 180; ANY-NEXT: [[TMP1:%.*]] = call double @sin(double [[X:%.*]]) 181; ANY-NEXT: [[R:%.*]] = fneg double [[TMP1]] 182; ANY-NEXT: ret double [[R]] 183; 184 %neg = fsub double -0.0, %x 185 %r = call double @sin(double %neg) 186 ret double %r 187} 188 189define double @sin_unary_negated_arg(double %x) { 190; ANY-LABEL: @sin_unary_negated_arg( 191; ANY-NEXT: [[TMP1:%.*]] = call double @sin(double [[X:%.*]]) 192; ANY-NEXT: [[R:%.*]] = fneg double [[TMP1]] 193; ANY-NEXT: ret double [[R]] 194; 195 %neg = fneg double %x 196 %r = call double @sin(double %neg) 197 ret double %r 198} 199 200define double @sin_unary_negated_arg_musttail(double %x) { 201; ANY-LABEL: @sin_unary_negated_arg_musttail( 202; ANY-NEXT: [[NEG:%.*]] = fneg double [[X:%.*]] 203; ANY-NEXT: [[R:%.*]] = musttail call double @sin(double [[NEG]]) 204; ANY-NEXT: ret double [[R]] 205; 206 %neg = fneg double %x 207 %r = musttail call double @sin(double %neg) 208 ret double %r 209} 210 211define float @sinf_negated_arg(float %x) { 212; ANY-LABEL: @sinf_negated_arg( 213; ANY-NEXT: [[TMP1:%.*]] = call float @sinf(float [[X:%.*]]) 214; ANY-NEXT: [[R:%.*]] = fneg float [[TMP1]] 215; ANY-NEXT: ret float [[R]] 216; 217 %neg = fsub float -0.0, %x 218 %r = call float @sinf(float %neg) 219 ret float %r 220} 221 222define float @sinf_unary_negated_arg(float %x) { 223; ANY-LABEL: @sinf_unary_negated_arg( 224; ANY-NEXT: [[TMP1:%.*]] = call float @sinf(float [[X:%.*]]) 225; ANY-NEXT: [[R:%.*]] = fneg float [[TMP1]] 226; ANY-NEXT: ret float [[R]] 227; 228 %neg = fneg float %x 229 %r = call float @sinf(float %neg) 230 ret float %r 231} 232 233define float @sinf_negated_arg_FMF(float %x) { 234; ANY-LABEL: @sinf_negated_arg_FMF( 235; ANY-NEXT: [[TMP1:%.*]] = call nnan afn float @sinf(float [[X:%.*]]) 236; ANY-NEXT: [[R:%.*]] = fneg nnan afn float [[TMP1]] 237; ANY-NEXT: ret float [[R]] 238; 239 %neg = fsub ninf float -0.0, %x 240 %r = call afn nnan float @sinf(float %neg) 241 ret float %r 242} 243 244define float @sinf_unary_negated_arg_FMF(float %x) { 245; ANY-LABEL: @sinf_unary_negated_arg_FMF( 246; ANY-NEXT: [[TMP1:%.*]] = call nnan afn float @sinf(float [[X:%.*]]) 247; ANY-NEXT: [[R:%.*]] = fneg nnan afn float [[TMP1]] 248; ANY-NEXT: ret float [[R]] 249; 250 %neg = fneg ninf float %x 251 %r = call afn nnan float @sinf(float %neg) 252 ret float %r 253} 254 255declare void @use(double) 256 257define double @sin_negated_arg_extra_use(double %x) { 258; ANY-LABEL: @sin_negated_arg_extra_use( 259; ANY-NEXT: [[NEG:%.*]] = fneg double [[X:%.*]] 260; ANY-NEXT: [[R:%.*]] = call double @sin(double [[NEG]]) 261; ANY-NEXT: call void @use(double [[NEG]]) 262; ANY-NEXT: ret double [[R]] 263; 264 %neg = fsub double -0.0, %x 265 %r = call double @sin(double %neg) 266 call void @use(double %neg) 267 ret double %r 268} 269 270define double @sin_unary_negated_arg_extra_use(double %x) { 271; ANY-LABEL: @sin_unary_negated_arg_extra_use( 272; ANY-NEXT: [[NEG:%.*]] = fneg double [[X:%.*]] 273; ANY-NEXT: [[R:%.*]] = call double @sin(double [[NEG]]) 274; ANY-NEXT: call void @use(double [[NEG]]) 275; ANY-NEXT: ret double [[R]] 276; 277 %neg = fneg double %x 278 %r = call double @sin(double %neg) 279 call void @use(double %neg) 280 ret double %r 281} 282 283; -sin(-x) --> sin(x) 284; PR38458: https://bugs.llvm.org/show_bug.cgi?id=38458 285 286define double @neg_sin_negated_arg(double %x) { 287; ANY-LABEL: @neg_sin_negated_arg( 288; ANY-NEXT: [[TMP1:%.*]] = call double @sin(double [[X:%.*]]) 289; ANY-NEXT: ret double [[TMP1]] 290; 291 %neg = fsub double -0.0, %x 292 %r = call double @sin(double %neg) 293 %rn = fsub double -0.0, %r 294 ret double %rn 295} 296 297define double @unary_neg_sin_unary_negated_arg(double %x) { 298; ANY-LABEL: @unary_neg_sin_unary_negated_arg( 299; ANY-NEXT: [[TMP1:%.*]] = call double @sin(double [[X:%.*]]) 300; ANY-NEXT: ret double [[TMP1]] 301; 302 %neg = fneg double %x 303 %r = call double @sin(double %neg) 304 %rn = fneg double %r 305 ret double %rn 306} 307 308define double @neg_sin_unary_negated_arg(double %x) { 309; ANY-LABEL: @neg_sin_unary_negated_arg( 310; ANY-NEXT: [[TMP1:%.*]] = call double @sin(double [[X:%.*]]) 311; ANY-NEXT: ret double [[TMP1]] 312; 313 %neg = fsub double -0.0, %x 314 %r = call double @sin(double %neg) 315 %rn = fneg double %r 316 ret double %rn 317} 318 319define double @unary_neg_sin_negated_arg(double %x) { 320; ANY-LABEL: @unary_neg_sin_negated_arg( 321; ANY-NEXT: [[TMP1:%.*]] = call double @sin(double [[X:%.*]]) 322; ANY-NEXT: ret double [[TMP1]] 323; 324 %neg = fneg double %x 325 %r = call double @sin(double %neg) 326 %rn = fsub double -0.0, %r 327 ret double %rn 328} 329 330; tan(-x) -> -tan(x); 331 332define double @tan_negated_arg(double %x) { 333; ANY-LABEL: @tan_negated_arg( 334; ANY-NEXT: [[TMP1:%.*]] = call double @tan(double [[X:%.*]]) 335; ANY-NEXT: [[R:%.*]] = fneg double [[TMP1]] 336; ANY-NEXT: ret double [[R]] 337; 338 %neg = fsub double -0.0, %x 339 %r = call double @tan(double %neg) 340 ret double %r 341} 342 343define double @tan_negated_arg_tail(double %x) { 344; ANY-LABEL: @tan_negated_arg_tail( 345; ANY-NEXT: [[TMP1:%.*]] = tail call double @tan(double [[X:%.*]]) 346; ANY-NEXT: [[R:%.*]] = fneg double [[TMP1]] 347; ANY-NEXT: ret double [[R]] 348; 349 %neg = fsub double -0.0, %x 350 %r = tail call double @tan(double %neg) 351 ret double %r 352} 353define double @tan_negated_arg_musttail(double %x) { 354; ANY-LABEL: @tan_negated_arg_musttail( 355; ANY-NEXT: [[NEG:%.*]] = fneg double [[X:%.*]] 356; ANY-NEXT: [[R:%.*]] = musttail call double @tan(double [[NEG]]) 357; ANY-NEXT: ret double [[R]] 358; 359 %neg = fsub double -0.0, %x 360 %r = musttail call double @tan(double %neg) 361 ret double %r 362} 363 364define double @tan_unary_negated_arg(double %x) { 365; ANY-LABEL: @tan_unary_negated_arg( 366; ANY-NEXT: [[TMP1:%.*]] = call double @tan(double [[X:%.*]]) 367; ANY-NEXT: [[R:%.*]] = fneg double [[TMP1]] 368; ANY-NEXT: ret double [[R]] 369; 370 %neg = fneg double %x 371 %r = call double @tan(double %neg) 372 ret double %r 373} 374 375; tanl(-x) -> -tanl(x); 376 377define fp128 @tanl_negated_arg(fp128 %x) { 378; ANY-LABEL: @tanl_negated_arg( 379; ANY-NEXT: [[TMP1:%.*]] = call fp128 @tanl(fp128 [[X:%.*]]) 380; ANY-NEXT: [[R:%.*]] = fneg fp128 [[TMP1]] 381; ANY-NEXT: ret fp128 [[R]] 382; 383 %neg = fsub fp128 0xL00000000000000008000000000000000, %x 384 %r = call fp128 @tanl(fp128 %neg) 385 ret fp128 %r 386} 387 388define fp128 @tanl_unary_negated_arg(fp128 %x) { 389; ANY-LABEL: @tanl_unary_negated_arg( 390; ANY-NEXT: [[TMP1:%.*]] = call fp128 @tanl(fp128 [[X:%.*]]) 391; ANY-NEXT: [[R:%.*]] = fneg fp128 [[TMP1]] 392; ANY-NEXT: ret fp128 [[R]] 393; 394 %neg = fneg fp128 %x 395 %r = call fp128 @tanl(fp128 %neg) 396 ret fp128 %r 397} 398 399define float @negated_and_shrinkable_libcall(float %f) { 400; NO-FLOAT-SHRINK-LABEL: @negated_and_shrinkable_libcall( 401; NO-FLOAT-SHRINK-NEXT: [[CONV1:%.*]] = fpext float [[F:%.*]] to double 402; NO-FLOAT-SHRINK-NEXT: [[COS1:%.*]] = call double @cos(double [[CONV1]]) 403; NO-FLOAT-SHRINK-NEXT: [[CONV2:%.*]] = fptrunc double [[COS1]] to float 404; NO-FLOAT-SHRINK-NEXT: ret float [[CONV2]] 405; 406; DO-FLOAT-SHRINK-LABEL: @negated_and_shrinkable_libcall( 407; DO-FLOAT-SHRINK-NEXT: [[COSF:%.*]] = call float @cosf(float [[F:%.*]]) 408; DO-FLOAT-SHRINK-NEXT: ret float [[COSF]] 409; 410 %conv1 = fpext float %f to double 411 %neg = fsub double -0.0, %conv1 412 %cos = call double @cos(double %neg) 413 %conv2 = fptrunc double %cos to float 414 ret float %conv2 415} 416 417define float @unary_negated_and_shrinkable_libcall(float %f) { 418; NO-FLOAT-SHRINK-LABEL: @unary_negated_and_shrinkable_libcall( 419; NO-FLOAT-SHRINK-NEXT: [[CONV1:%.*]] = fpext float [[F:%.*]] to double 420; NO-FLOAT-SHRINK-NEXT: [[COS1:%.*]] = call double @cos(double [[CONV1]]) 421; NO-FLOAT-SHRINK-NEXT: [[CONV2:%.*]] = fptrunc double [[COS1]] to float 422; NO-FLOAT-SHRINK-NEXT: ret float [[CONV2]] 423; 424; DO-FLOAT-SHRINK-LABEL: @unary_negated_and_shrinkable_libcall( 425; DO-FLOAT-SHRINK-NEXT: [[COSF:%.*]] = call float @cosf(float [[F:%.*]]) 426; DO-FLOAT-SHRINK-NEXT: ret float [[COSF]] 427; 428 %conv1 = fpext float %f to double 429 %neg = fneg double %conv1 430 %cos = call double @cos(double %neg) 431 %conv2 = fptrunc double %cos to float 432 ret float %conv2 433} 434 435; TODO: It was ok to shrink the libcall, so the intrinsic should shrink too? 436 437define float @negated_and_shrinkable_intrinsic(float %f) { 438; ANY-LABEL: @negated_and_shrinkable_intrinsic( 439; ANY-NEXT: [[CONV1:%.*]] = fpext float [[F:%.*]] to double 440; ANY-NEXT: [[COS:%.*]] = call double @llvm.cos.f64(double [[CONV1]]) 441; ANY-NEXT: [[CONV2:%.*]] = fptrunc double [[COS]] to float 442; ANY-NEXT: ret float [[CONV2]] 443; 444 %conv1 = fpext float %f to double 445 %neg = fsub double -0.0, %conv1 446 %cos = call double @llvm.cos.f64(double %neg) 447 %conv2 = fptrunc double %cos to float 448 ret float %conv2 449} 450 451define float @unary_negated_and_shrinkable_intrinsic(float %f) { 452; ANY-LABEL: @unary_negated_and_shrinkable_intrinsic( 453; ANY-NEXT: [[CONV1:%.*]] = fpext float [[F:%.*]] to double 454; ANY-NEXT: [[COS:%.*]] = call double @llvm.cos.f64(double [[CONV1]]) 455; ANY-NEXT: [[CONV2:%.*]] = fptrunc double [[COS]] to float 456; ANY-NEXT: ret float [[CONV2]] 457; 458 %conv1 = fpext float %f to double 459 %neg = fneg double %conv1 460 %cos = call double @llvm.cos.f64(double %neg) 461 %conv2 = fptrunc double %cos to float 462 ret float %conv2 463} 464