1; RUN: opt -S -instcombine < %s | FileCheck %s 2target 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" 3target triple = "x86_64-apple-macosx10.8.0" 4 5define i1 @test1(float %x, float %y) { 6; CHECK-LABEL: @test1( 7; CHECK-NEXT: [[CEIL:%.*]] = call float @llvm.ceil.f32(float %x) 8; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[CEIL]], %y 9; CHECK-NEXT: ret i1 [[CMP]] 10; 11 %x.ext = fpext float %x to double 12 %ceil = call double @ceil(double %x.ext) nounwind readnone 13 %ext.y = fpext float %y to double 14 %cmp = fcmp oeq double %ceil, %ext.y 15 ret i1 %cmp 16} 17 18define i1 @test1_intrin(float %x, float %y) { 19; CHECK-LABEL: @test1_intrin( 20; CHECK-NEXT: [[CEIL:%.*]] = call float @llvm.ceil.f32(float %x) 21; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[CEIL]], %y 22; CHECK-NEXT: ret i1 [[CMP]] 23; 24 %x.ext = fpext float %x to double 25 %ceil = call double @llvm.ceil.f64(double %x.ext) nounwind readnone 26 %ext.y = fpext float %y to double 27 %cmp = fcmp oeq double %ceil, %ext.y 28 ret i1 %cmp 29} 30 31define i1 @test2(float %x, float %y) { 32; CHECK-LABEL: @test2( 33; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float %x) 34; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[FABS]], %y 35; CHECK-NEXT: ret i1 [[CMP]] 36; 37 %x.ext = fpext float %x to double 38 %fabs = call double @fabs(double %x.ext) nounwind readnone 39 %y.ext = fpext float %y to double 40 %cmp = fcmp oeq double %fabs, %y.ext 41 ret i1 %cmp 42} 43 44define i1 @test2_intrin(float %x, float %y) { 45; CHECK-LABEL: @test2_intrin( 46; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float %x) 47; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[FABS]], %y 48; CHECK-NEXT: ret i1 [[CMP]] 49; 50 %x.ext = fpext float %x to double 51 %fabs = call double @llvm.fabs.f64(double %x.ext) nounwind readnone 52 %y.ext = fpext float %y to double 53 %cmp = fcmp oeq double %fabs, %y.ext 54 ret i1 %cmp 55} 56 57define i1 @fmf_test2(float %x, float %y) { 58; CHECK-LABEL: @fmf_test2( 59; CHECK-NEXT: [[TMP1:%.*]] = call nnan float @llvm.fabs.f32(float %x) 60; CHECK-NEXT: [[TMP2:%.*]] = fcmp oeq float [[TMP1]], %y 61; CHECK-NEXT: ret i1 [[TMP2]] 62; 63 %1 = fpext float %x to double 64 %2 = call nnan double @fabs(double %1) nounwind readnone 65 %3 = fpext float %y to double 66 %4 = fcmp oeq double %2, %3 67 ret i1 %4 68} 69 70define i1 @test3(float %x, float %y) { 71; CHECK-LABEL: @test3( 72; CHECK-NEXT: [[FLOOR:%.*]] = call float @llvm.floor.f32(float %x) 73; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[FLOOR]], %y 74; CHECK-NEXT: ret i1 [[CMP]] 75; 76 %x.ext = fpext float %x to double 77 %floor = call double @floor(double %x.ext) nounwind readnone 78 %y.ext = fpext float %y to double 79 %cmp = fcmp oeq double %floor, %y.ext 80 ret i1 %cmp 81} 82 83 84define i1 @test3_intrin(float %x, float %y) { 85; CHECK-LABEL: @test3_intrin( 86; CHECK-NEXT: [[FLOOR:%.*]] = call float @llvm.floor.f32(float %x) 87; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[FLOOR]], %y 88; CHECK-NEXT: ret i1 [[CMP]] 89; 90 %x.ext = fpext float %x to double 91 %floor = call double @llvm.floor.f64(double %x.ext) nounwind readnone 92 %y.ext = fpext float %y to double 93 %cmp = fcmp oeq double %floor, %y.ext 94 ret i1 %cmp 95} 96 97define i1 @test4(float %x, float %y) { 98; CHECK-LABEL: @test4( 99; CHECK-NEXT: [[NEARBYINT:%.*]] = call float @llvm.nearbyint.f32(float %x) 100; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[NEARBYINT]], %y 101; CHECK-NEXT: ret i1 [[CMP]] 102; 103 %x.ext = fpext float %x to double 104 %nearbyint = call double @nearbyint(double %x.ext) nounwind 105 %y.ext = fpext float %y to double 106 %cmp = fcmp oeq double %nearbyint, %y.ext 107 ret i1 %cmp 108} 109 110define i1 @shrink_nearbyint_intrin(float %x, float %y) { 111; CHECK-LABEL: @shrink_nearbyint_intrin( 112; CHECK-NEXT: [[NEARBYINT:%.*]] = call float @llvm.nearbyint.f32(float %x) 113; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[NEARBYINT]], %y 114; CHECK-NEXT: ret i1 [[CMP]] 115; 116 %x.ext = fpext float %x to double 117 %nearbyint = call double @llvm.nearbyint.f64(double %x.ext) nounwind 118 %y.ext = fpext float %y to double 119 %cmp = fcmp oeq double %nearbyint, %y.ext 120 ret i1 %cmp 121} 122 123define i1 @test5(float %x, float %y) { 124; CHECK-LABEL: @test5( 125; CHECK-NEXT: [[RINT:%.*]] = call float @llvm.rint.f32(float %x) 126; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[RINT]], %y 127; CHECK-NEXT: ret i1 [[CMP]] 128; 129 %x.ext = fpext float %x to double 130 %rint = call double @rint(double %x.ext) nounwind 131 %y.ext = fpext float %y to double 132 %cmp = fcmp oeq double %rint, %y.ext 133 ret i1 %cmp 134} 135 136define i1 @test6(float %x, float %y) { 137; CHECK-LABEL: @test6( 138; CHECK-NEXT: [[ROUND:%.*]] = call float @llvm.round.f32(float %x) 139; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[ROUND]], %y 140; CHECK-NEXT: ret i1 [[CMP]] 141; 142 %x.ext = fpext float %x to double 143 %round = call double @round(double %x.ext) nounwind readnone 144 %y.ext = fpext float %y to double 145 %cmp = fcmp oeq double %round, %y.ext 146 ret i1 %cmp 147} 148 149define i1 @test6_intrin(float %x, float %y) { 150; CHECK-LABEL: @test6_intrin( 151; CHECK-NEXT: [[ROUND:%.*]] = call float @llvm.round.f32(float %x) 152; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[ROUND]], %y 153; CHECK-NEXT: ret i1 [[CMP]] 154; 155 %x.ext = fpext float %x to double 156 %round = call double @llvm.round.f64(double %x.ext) nounwind readnone 157 %y.ext = fpext float %y to double 158 %cmp = fcmp oeq double %round, %y.ext 159 ret i1 %cmp 160} 161 162define i1 @test7(float %x, float %y) { 163; CHECK-LABEL: @test7( 164; CHECK-NEXT: [[TRUNC:%.*]] = call float @llvm.trunc.f32(float %x) 165; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[TRUNC]], %y 166; CHECK-NEXT: ret i1 [[CMP]] 167; 168 %x.ext = fpext float %x to double 169 %trunc = call double @trunc(double %x.ext) nounwind 170 %y.ext = fpext float %y to double 171 %cmp = fcmp oeq double %trunc, %y.ext 172 ret i1 %cmp 173} 174 175define i1 @test7_intrin(float %x, float %y) { 176; CHECK-LABEL: @test7_intrin( 177; CHECK-NEXT: [[TRUNC:%.*]] = call float @llvm.trunc.f32(float %x) 178; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[TRUNC]], %y 179; CHECK-NEXT: ret i1 [[CMP]] 180; 181 %x.ext = fpext float %x to double 182 %trunc = call double @llvm.trunc.f64(double %x.ext) nounwind 183 %y.ext = fpext float %y to double 184 %cmp = fcmp oeq double %trunc, %y.ext 185 ret i1 %cmp 186} 187 188define i1 @test8(float %x, float %y) { 189; CHECK-LABEL: @test8( 190; CHECK-NEXT: [[CEIL:%.*]] = call float @llvm.ceil.f32(float %x) 191; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[CEIL]], %y 192; CHECK-NEXT: ret i1 [[CMP]] 193; 194 %x.ext = fpext float %x to double 195 %y.ext = fpext float %y to double 196 %ceil = call double @ceil(double %x.ext) nounwind readnone 197 %cmp = fcmp oeq double %y.ext, %ceil 198 ret i1 %cmp 199} 200 201define i1 @test8_intrin(float %x, float %y) { 202; CHECK-LABEL: @test8_intrin( 203; CHECK-NEXT: [[CEIL:%.*]] = call float @llvm.ceil.f32(float %x) 204; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[CEIL]], %y 205; CHECK-NEXT: ret i1 [[CMP]] 206; 207 %x.ext = fpext float %x to double 208 %y.ext = fpext float %y to double 209 %ceil = call double @llvm.ceil.f64(double %x.ext) nounwind readnone 210 %cmp = fcmp oeq double %y.ext, %ceil 211 ret i1 %cmp 212} 213 214define i1 @test9(float %x, float %y) { 215; CHECK-LABEL: @test9( 216; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float %x) 217; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[FABS]], %y 218; CHECK-NEXT: ret i1 [[CMP]] 219; 220 %x.ext = fpext float %x to double 221 %y.ext = fpext float %y to double 222 %fabs = call double @fabs(double %x.ext) nounwind readnone 223 %cmp = fcmp oeq double %y.ext, %fabs 224 ret i1 %cmp 225} 226 227define i1 @test9_intrin(float %x, float %y) { 228; CHECK-LABEL: @test9_intrin( 229; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float %x) 230; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[FABS]], %y 231; CHECK-NEXT: ret i1 [[CMP]] 232; 233 %x.ext = fpext float %x to double 234 %y.ext = fpext float %y to double 235 %fabs = call double @llvm.fabs.f64(double %x.ext) nounwind readnone 236 %cmp = fcmp oeq double %y.ext, %fabs 237 ret i1 %cmp 238} 239 240define i1 @test10(float %x, float %y) { 241; CHECK-LABEL: @test10( 242; CHECK-NEXT: [[FLOOR:%.*]] = call float @llvm.floor.f32(float %x) 243; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[FLOOR]], %y 244; CHECK-NEXT: ret i1 [[CMP]] 245; 246 %x.ext = fpext float %x to double 247 %y.ext = fpext float %y to double 248 %floor = call double @floor(double %x.ext) nounwind readnone 249 %cmp = fcmp oeq double %floor, %y.ext 250 ret i1 %cmp 251} 252 253define i1 @test10_intrin(float %x, float %y) { 254; CHECK-LABEL: @test10_intrin( 255; CHECK-NEXT: [[FLOOR:%.*]] = call float @llvm.floor.f32(float %x) 256; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[FLOOR]], %y 257; CHECK-NEXT: ret i1 [[CMP]] 258; 259 %x.ext = fpext float %x to double 260 %y.ext = fpext float %y to double 261 %floor = call double @llvm.floor.f64(double %x.ext) nounwind readnone 262 %cmp = fcmp oeq double %floor, %y.ext 263 ret i1 %cmp 264} 265 266define i1 @test11(float %x, float %y) { 267; CHECK-LABEL: @test11( 268; CHECK-NEXT: [[NEARBYINT:%.*]] = call float @llvm.nearbyint.f32(float %x) 269; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[NEARBYINT]], %y 270; CHECK-NEXT: ret i1 [[CMP]] 271; 272 %x.ext = fpext float %x to double 273 %y.ext = fpext float %y to double 274 %nearbyint = call double @nearbyint(double %x.ext) nounwind 275 %cmp = fcmp oeq double %nearbyint, %y.ext 276 ret i1 %cmp 277} 278 279define i1 @test11_intrin(float %x, float %y) { 280; CHECK-LABEL: @test11_intrin( 281; CHECK-NEXT: [[NEARBYINT:%.*]] = call float @llvm.nearbyint.f32(float %x) 282; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[NEARBYINT]], %y 283; CHECK-NEXT: ret i1 [[CMP]] 284; 285 %x.ext = fpext float %x to double 286 %y.ext = fpext float %y to double 287 %nearbyint = call double @llvm.nearbyint.f64(double %x.ext) nounwind 288 %cmp = fcmp oeq double %nearbyint, %y.ext 289 ret i1 %cmp 290} 291 292define i1 @test12(float %x, float %y) { 293; CHECK-LABEL: @test12( 294; CHECK-NEXT: [[RINT:%.*]] = call float @llvm.rint.f32(float %x) 295; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[RINT]], %y 296; CHECK-NEXT: ret i1 [[CMP]] 297; 298 %x.ext = fpext float %x to double 299 %y.ext = fpext float %y to double 300 %rint = call double @rint(double %x.ext) nounwind 301 %cmp = fcmp oeq double %y.ext, %rint 302 ret i1 %cmp 303} 304 305define i1 @test13(float %x, float %y) { 306; CHECK-LABEL: @test13( 307; CHECK-NEXT: [[ROUND:%.*]] = call float @llvm.round.f32(float %x) 308; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[ROUND]], %y 309; CHECK-NEXT: ret i1 [[CMP]] 310; 311 %x.ext = fpext float %x to double 312 %y.ext = fpext float %y to double 313 %round = call double @round(double %x.ext) nounwind readnone 314 %cmp = fcmp oeq double %y.ext, %round 315 ret i1 %cmp 316} 317 318define i1 @test13_intrin(float %x, float %y) { 319; CHECK-LABEL: @test13_intrin( 320; CHECK-NEXT: [[ROUND:%.*]] = call float @llvm.round.f32(float %x) 321; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[ROUND]], %y 322; CHECK-NEXT: ret i1 [[CMP]] 323; 324 %x.ext = fpext float %x to double 325 %y.ext = fpext float %y to double 326 %round = call double @llvm.round.f64(double %x.ext) nounwind readnone 327 %cmp = fcmp oeq double %y.ext, %round 328 ret i1 %cmp 329} 330 331define i1 @test14(float %x, float %y) { 332; CHECK-LABEL: @test14( 333; CHECK-NEXT: [[TRUNC:%.*]] = call float @llvm.trunc.f32(float %x) 334; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[TRUNC]], %y 335; CHECK-NEXT: ret i1 [[CMP]] 336; 337 %x.ext = fpext float %x to double 338 %y.ext = fpext float %y to double 339 %trunc = call double @trunc(double %x.ext) nounwind 340 %cmp = fcmp oeq double %y.ext, %trunc 341 ret i1 %cmp 342} 343 344define i1 @test14_intrin(float %x, float %y) { 345; CHECK-LABEL: @test14_intrin( 346; CHECK-NEXT: [[TRUNC:%.*]] = call float @llvm.trunc.f32(float %x) 347; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[TRUNC]], %y 348; CHECK-NEXT: ret i1 [[CMP]] 349; 350 %x.ext = fpext float %x to double 351 %y.ext = fpext float %y to double 352 %trunc = call double @llvm.trunc.f64(double %x.ext) nounwind 353 %cmp = fcmp oeq double %y.ext, %trunc 354 ret i1 %cmp 355} 356 357define i1 @test15(float %x, float %y, float %z) { 358; CHECK-LABEL: @test15( 359; CHECK-NEXT: [[FMINF:%.*]] = call float @fminf(float %x, float %y) #0 360; CHECK-NEXT: [[TMP1:%.*]] = fcmp oeq float [[FMINF]], %z 361; CHECK-NEXT: ret i1 [[TMP1]] 362; 363 %1 = fpext float %x to double 364 %2 = fpext float %y to double 365 %3 = call double @fmin(double %1, double %2) nounwind 366 %4 = fpext float %z to double 367 %5 = fcmp oeq double %3, %4 368 ret i1 %5 369} 370 371define i1 @test16(float %x, float %y, float %z) { 372; CHECK-LABEL: @test16( 373; CHECK-NEXT: [[FMINF:%.*]] = call float @fminf(float %x, float %y) #0 374; CHECK-NEXT: [[TMP1:%.*]] = fcmp oeq float [[FMINF]], %z 375; CHECK-NEXT: ret i1 [[TMP1]] 376; 377 %1 = fpext float %z to double 378 %2 = fpext float %x to double 379 %3 = fpext float %y to double 380 %4 = call double @fmin(double %2, double %3) nounwind 381 %5 = fcmp oeq double %1, %4 382 ret i1 %5 383} 384 385define i1 @test17(float %x, float %y, float %z) { 386; CHECK-LABEL: @test17( 387; CHECK-NEXT: [[FMAXF:%.*]] = call float @fmaxf(float %x, float %y) #0 388; CHECK-NEXT: [[TMP1:%.*]] = fcmp oeq float [[FMAXF]], %z 389; CHECK-NEXT: ret i1 [[TMP1]] 390; 391 %1 = fpext float %x to double 392 %2 = fpext float %y to double 393 %3 = call double @fmax(double %1, double %2) nounwind 394 %4 = fpext float %z to double 395 %5 = fcmp oeq double %3, %4 396 ret i1 %5 397} 398 399define i1 @test18(float %x, float %y, float %z) { 400; CHECK-LABEL: @test18( 401; CHECK-NEXT: [[FMAXF:%.*]] = call float @fmaxf(float %x, float %y) #0 402; CHECK-NEXT: [[TMP1:%.*]] = fcmp oeq float [[FMAXF]], %z 403; CHECK-NEXT: ret i1 [[TMP1]] 404; 405 %1 = fpext float %z to double 406 %2 = fpext float %x to double 407 %3 = fpext float %y to double 408 %4 = call double @fmax(double %2, double %3) nounwind 409 %5 = fcmp oeq double %1, %4 410 ret i1 %5 411} 412 413define i1 @test19(float %x, float %y, float %z) { 414; CHECK-LABEL: @test19( 415; CHECK-NEXT: [[COPYSIGNF:%.*]] = call float @copysignf(float %x, float %y) #0 416; CHECK-NEXT: [[TMP1:%.*]] = fcmp oeq float [[COPYSIGNF]], %z 417; CHECK-NEXT: ret i1 [[TMP1]] 418; 419 %1 = fpext float %x to double 420 %2 = fpext float %y to double 421 %3 = call double @copysign(double %1, double %2) nounwind 422 %4 = fpext float %z to double 423 %5 = fcmp oeq double %3, %4 424 ret i1 %5 425} 426 427define i1 @test20(float %x, float %y) { 428; CHECK-LABEL: @test20( 429; CHECK-NEXT: [[FMINF:%.*]] = call float @fminf(float 1.000000e+00, float %x) #0 430; CHECK-NEXT: [[TMP1:%.*]] = fcmp oeq float [[FMINF]], %y 431; CHECK-NEXT: ret i1 [[TMP1]] 432; 433 %1 = fpext float %y to double 434 %2 = fpext float %x to double 435 %3 = call double @fmin(double 1.000000e+00, double %2) nounwind 436 %4 = fcmp oeq double %1, %3 437 ret i1 %4 438} 439 440; should not be changed to fminf as the constant would lose precision 441 442define i1 @test21(float %x, float %y) { 443; CHECK-LABEL: @test21( 444; CHECK-NEXT: [[TMP1:%.*]] = fpext float %y to double 445; CHECK-NEXT: [[TMP2:%.*]] = fpext float %x to double 446; CHECK-NEXT: [[TMP3:%.*]] = call double @fmin(double 1.300000e+00, double [[TMP2]]) #2 447; CHECK-NEXT: [[TMP4:%.*]] = fcmp oeq double [[TMP3]], [[TMP1]] 448; CHECK-NEXT: ret i1 [[TMP4]] 449; 450 %1 = fpext float %y to double 451 %2 = fpext float %x to double 452 %3 = call double @fmin(double 1.300000e+00, double %2) nounwind 453 %4 = fcmp oeq double %1, %3 454 ret i1 %4 455} 456 457declare double @fabs(double) nounwind readnone 458declare double @ceil(double) nounwind readnone 459declare double @copysign(double, double) nounwind readnone 460declare double @floor(double) nounwind readnone 461declare double @nearbyint(double) nounwind readnone 462declare double @rint(double) nounwind readnone 463declare double @round(double) nounwind readnone 464declare double @trunc(double) nounwind readnone 465declare double @fmin(double, double) nounwind readnone 466declare double @fmax(double, double) nounwind readnone 467 468declare double @llvm.fabs.f64(double) nounwind readnone 469declare double @llvm.ceil.f64(double) nounwind readnone 470declare double @llvm.floor.f64(double) nounwind readnone 471declare double @llvm.nearbyint.f64(double) nounwind readnone 472declare double @llvm.round.f64(double) nounwind readnone 473declare double @llvm.trunc.f64(double) nounwind readnone 474