1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; Test some floating point casting cases 3; RUN: opt < %s -passes=instcombine -S | FileCheck %s 4 5define i8 @test1() { 6; CHECK-LABEL: @test1( 7; CHECK-NEXT: ret i8 -1 8; 9 %x = fptoui float 2.550000e+02 to i8 10 ret i8 %x 11} 12 13define i8 @test2() { 14; CHECK-LABEL: @test2( 15; CHECK-NEXT: ret i8 -1 16; 17 %x = fptosi float -1.000000e+00 to i8 18 ret i8 %x 19} 20 21define half @test3(float %a) { 22; CHECK-LABEL: @test3( 23; CHECK-NEXT: [[TMP1:%.*]] = fptrunc float [[A:%.*]] to half 24; CHECK-NEXT: [[C:%.*]] = call half @llvm.fabs.f16(half [[TMP1]]) 25; CHECK-NEXT: ret half [[C]] 26; 27 %b = call float @llvm.fabs.f32(float %a) 28 %c = fptrunc float %b to half 29 ret half %c 30} 31 32define half @test3_fast(float %a) { 33; CHECK-LABEL: @test3_fast( 34; CHECK-NEXT: [[TMP1:%.*]] = fptrunc float [[A:%.*]] to half 35; CHECK-NEXT: [[C:%.*]] = call half @llvm.fabs.f16(half [[TMP1]]) 36; CHECK-NEXT: ret half [[C]] 37; 38 %b = call float @llvm.fabs.f32(float %a) 39 %c = fptrunc fast float %b to half 40 ret half %c 41} 42 43define half @fneg_fptrunc(float %a) { 44; CHECK-LABEL: @fneg_fptrunc( 45; CHECK-NEXT: [[TMP1:%.*]] = fptrunc float [[A:%.*]] to half 46; CHECK-NEXT: [[C:%.*]] = fneg half [[TMP1]] 47; CHECK-NEXT: ret half [[C]] 48; 49 %b = fsub float -0.0, %a 50 %c = fptrunc float %b to half 51 ret half %c 52} 53 54define half @unary_fneg_fptrunc(float %a) { 55; CHECK-LABEL: @unary_fneg_fptrunc( 56; CHECK-NEXT: [[TMP1:%.*]] = fptrunc float [[A:%.*]] to half 57; CHECK-NEXT: [[C:%.*]] = fneg half [[TMP1]] 58; CHECK-NEXT: ret half [[C]] 59; 60 %b = fneg float %a 61 %c = fptrunc float %b to half 62 ret half %c 63} 64 65define <2 x half> @fneg_fptrunc_vec_poison(<2 x float> %a) { 66; CHECK-LABEL: @fneg_fptrunc_vec_poison( 67; CHECK-NEXT: [[TMP1:%.*]] = fptrunc <2 x float> [[A:%.*]] to <2 x half> 68; CHECK-NEXT: [[C:%.*]] = fneg <2 x half> [[TMP1]] 69; CHECK-NEXT: ret <2 x half> [[C]] 70; 71 %b = fsub <2 x float> <float -0.0, float poison>, %a 72 %c = fptrunc <2 x float> %b to <2 x half> 73 ret <2 x half> %c 74} 75 76define <2 x half> @unary_fneg_fptrunc_vec(<2 x float> %a) { 77; CHECK-LABEL: @unary_fneg_fptrunc_vec( 78; CHECK-NEXT: [[TMP1:%.*]] = fptrunc <2 x float> [[A:%.*]] to <2 x half> 79; CHECK-NEXT: [[C:%.*]] = fneg <2 x half> [[TMP1]] 80; CHECK-NEXT: ret <2 x half> [[C]] 81; 82 %b = fneg <2 x float> %a 83 %c = fptrunc <2 x float> %b to <2 x half> 84 ret <2 x half> %c 85} 86 87define half @test4-fast(float %a) { 88; CHECK-LABEL: @test4-fast( 89; CHECK-NEXT: [[TMP1:%.*]] = fptrunc fast float [[A:%.*]] to half 90; CHECK-NEXT: [[C:%.*]] = fneg fast half [[TMP1]] 91; CHECK-NEXT: ret half [[C]] 92; 93 %b = fsub fast float -0.0, %a 94 %c = fptrunc fast float %b to half 95 ret half %c 96} 97 98define half @test4-mixed-fast-1(float %a) { 99; CHECK-LABEL: @test4-mixed-fast-1( 100; CHECK-NEXT: [[TMP1:%.*]] = fptrunc float [[A:%.*]] to half 101; CHECK-NEXT: [[C:%.*]] = fneg half [[TMP1]] 102; CHECK-NEXT: ret half [[C]] 103; 104 %b = fsub float -0.0, %a 105 %c = fptrunc fast float %b to half 106 ret half %c 107} 108 109define half @test4-mixed-fast-2(float %a) { 110; CHECK-LABEL: @test4-mixed-fast-2( 111; CHECK-NEXT: [[TMP1:%.*]] = fptrunc float [[A:%.*]] to half 112; CHECK-NEXT: [[C:%.*]] = fneg half [[TMP1]] 113; CHECK-NEXT: ret half [[C]] 114; 115 %b = fsub fast float -0.0, %a 116 %c = fptrunc float %b to half 117 ret half %c 118} 119 120define half @test4_unary_fneg-fast(float %a) { 121; CHECK-LABEL: @test4_unary_fneg-fast( 122; CHECK-NEXT: [[TMP1:%.*]] = fptrunc fast float [[A:%.*]] to half 123; CHECK-NEXT: [[C:%.*]] = fneg fast half [[TMP1]] 124; CHECK-NEXT: ret half [[C]] 125; 126 %b = fneg fast float %a 127 %c = fptrunc fast float %b to half 128 ret half %c 129} 130 131define half @test4_unary_fneg-mixed-fast-1(float %a) { 132; CHECK-LABEL: @test4_unary_fneg-mixed-fast-1( 133; CHECK-NEXT: [[TMP1:%.*]] = fptrunc float [[A:%.*]] to half 134; CHECK-NEXT: [[C:%.*]] = fneg half [[TMP1]] 135; CHECK-NEXT: ret half [[C]] 136; 137 %b = fneg float %a 138 %c = fptrunc fast float %b to half 139 ret half %c 140} 141 142define half @test4_unary_fneg-mixed-fast-2(float %a) { 143; CHECK-LABEL: @test4_unary_fneg-mixed-fast-2( 144; CHECK-NEXT: [[TMP1:%.*]] = fptrunc float [[A:%.*]] to half 145; CHECK-NEXT: [[C:%.*]] = fneg half [[TMP1]] 146; CHECK-NEXT: ret half [[C]] 147; 148 %b = fneg fast float %a 149 %c = fptrunc float %b to half 150 ret half %c 151} 152 153define <2 x half> @test4_unary_fneg-vec-fast(<2 x float> %a) { 154; CHECK-LABEL: @test4_unary_fneg-vec-fast( 155; CHECK-NEXT: [[TMP1:%.*]] = fptrunc fast <2 x float> [[A:%.*]] to <2 x half> 156; CHECK-NEXT: [[C:%.*]] = fneg fast <2 x half> [[TMP1]] 157; CHECK-NEXT: ret <2 x half> [[C]] 158; 159 %b = fneg fast <2 x float> %a 160 %c = fptrunc fast <2 x float> %b to <2 x half> 161 ret <2 x half> %c 162} 163 164define <2 x half> @test4_unary_fneg-vec-mixed-fast-1(<2 x float> %a) { 165; CHECK-LABEL: @test4_unary_fneg-vec-mixed-fast-1( 166; CHECK-NEXT: [[TMP1:%.*]] = fptrunc <2 x float> [[A:%.*]] to <2 x half> 167; CHECK-NEXT: [[C:%.*]] = fneg <2 x half> [[TMP1]] 168; CHECK-NEXT: ret <2 x half> [[C]] 169; 170 %b = fneg <2 x float> %a 171 %c = fptrunc fast <2 x float> %b to <2 x half> 172 ret <2 x half> %c 173} 174 175define <2 x half> @test4_unary_fneg-vec-mixed-fast-2(<2 x float> %a) { 176; CHECK-LABEL: @test4_unary_fneg-vec-mixed-fast-2( 177; CHECK-NEXT: [[TMP1:%.*]] = fptrunc <2 x float> [[A:%.*]] to <2 x half> 178; CHECK-NEXT: [[C:%.*]] = fneg <2 x half> [[TMP1]] 179; CHECK-NEXT: ret <2 x half> [[C]] 180; 181 %b = fneg fast <2 x float> %a 182 %c = fptrunc <2 x float> %b to <2 x half> 183 ret <2 x half> %c 184} 185 186define half @test5(float %a, float %b, float %c) { 187; CHECK-LABEL: @test5( 188; CHECK-NEXT: [[D:%.*]] = fcmp ogt float [[A:%.*]], [[B:%.*]] 189; CHECK-NEXT: [[E:%.*]] = select i1 [[D]], float [[C:%.*]], float 1.000000e+00 190; CHECK-NEXT: [[F:%.*]] = fptrunc float [[E]] to half 191; CHECK-NEXT: ret half [[F]] 192; 193 %d = fcmp ogt float %a, %b 194 %e = select i1 %d, float %c, float 1.0 195 %f = fptrunc float %e to half 196 ret half %f 197} 198 199declare float @llvm.fabs.f32(float) nounwind readonly 200 201define <1 x float> @test6(<1 x double> %V) { 202; CHECK-LABEL: @test6( 203; CHECK-NEXT: [[FREM:%.*]] = frem <1 x double> [[V:%.*]], [[V]] 204; CHECK-NEXT: [[TRUNC:%.*]] = fptrunc <1 x double> [[FREM]] to <1 x float> 205; CHECK-NEXT: ret <1 x float> [[TRUNC]] 206; 207 %frem = frem <1 x double> %V, %V 208 %trunc = fptrunc <1 x double> %frem to <1 x float> 209 ret <1 x float> %trunc 210} 211 212define float @test7(double %V) { 213; CHECK-LABEL: @test7( 214; CHECK-NEXT: [[FREM:%.*]] = frem double [[V:%.*]], 1.000000e+00 215; CHECK-NEXT: [[TRUNC:%.*]] = fptrunc double [[FREM]] to float 216; CHECK-NEXT: ret float [[TRUNC]] 217; 218 %frem = frem double %V, 1.000000e+00 219 %trunc = fptrunc double %frem to float 220 ret float %trunc 221} 222 223define float @test8(float %V) { 224; CHECK-LABEL: @test8( 225; CHECK-NEXT: [[FEXT:%.*]] = fpext float [[V:%.*]] to double 226; CHECK-NEXT: [[FREM:%.*]] = frem double [[FEXT]], 1.000000e-01 227; CHECK-NEXT: [[TRUNC:%.*]] = fptrunc double [[FREM]] to float 228; CHECK-NEXT: ret float [[TRUNC]] 229; 230 %fext = fpext float %V to double 231 %frem = frem double %fext, 1.000000e-01 232 %trunc = fptrunc double %frem to float 233 ret float %trunc 234} 235 236define half @test_fptrunc_fptrunc(double %V) { 237; CHECK-LABEL: @test_fptrunc_fptrunc( 238; CHECK-NEXT: [[T1:%.*]] = fptrunc double [[V:%.*]] to float 239; CHECK-NEXT: [[T2:%.*]] = fptrunc float [[T1]] to half 240; CHECK-NEXT: ret half [[T2]] 241; 242 %t1 = fptrunc double %V to float 243 %t2 = fptrunc float %t1 to half 244 ret half %t2 245} 246 247define half @sint_to_fptrunc(i32 %x) { 248; CHECK-LABEL: @sint_to_fptrunc( 249; CHECK-NEXT: [[F:%.*]] = sitofp i32 [[X:%.*]] to float 250; CHECK-NEXT: [[R:%.*]] = fptrunc float [[F]] to half 251; CHECK-NEXT: ret half [[R]] 252; 253 %f = sitofp i32 %x to float 254 %r = fptrunc float %f to half 255 ret half %r 256} 257 258define half @masked_sint_to_fptrunc1(i32 %x) { 259; CHECK-LABEL: @masked_sint_to_fptrunc1( 260; CHECK-NEXT: [[M:%.*]] = and i32 [[X:%.*]], 16777215 261; CHECK-NEXT: [[R:%.*]] = uitofp nneg i32 [[M]] to half 262; CHECK-NEXT: ret half [[R]] 263; 264 %m = and i32 %x, 16777215 265 %f = sitofp i32 %m to float 266 %r = fptrunc float %f to half 267 ret half %r 268} 269 270define half @masked_sint_to_fptrunc2(i32 %x) { 271; CHECK-LABEL: @masked_sint_to_fptrunc2( 272; CHECK-NEXT: [[M:%.*]] = lshr i32 [[X:%.*]], 8 273; CHECK-NEXT: [[R:%.*]] = uitofp nneg i32 [[M]] to half 274; CHECK-NEXT: ret half [[R]] 275; 276 %m = lshr i32 %x, 8 277 %f = sitofp i32 %m to float 278 %r = fptrunc float %f to half 279 ret half %r 280} 281 282define half @masked_sint_to_fptrunc3(i32 %x) { 283; CHECK-LABEL: @masked_sint_to_fptrunc3( 284; CHECK-NEXT: [[M:%.*]] = lshr i32 [[X:%.*]], 7 285; CHECK-NEXT: [[F:%.*]] = uitofp nneg i32 [[M]] to float 286; CHECK-NEXT: [[R:%.*]] = fptrunc float [[F]] to half 287; CHECK-NEXT: ret half [[R]] 288; 289 %m = lshr i32 %x, 7 290 %f = sitofp i32 %m to float 291 %r = fptrunc float %f to half 292 ret half %r 293} 294 295define double @sint_to_fpext(i32 %x) { 296; CHECK-LABEL: @sint_to_fpext( 297; CHECK-NEXT: [[F:%.*]] = sitofp i32 [[X:%.*]] to float 298; CHECK-NEXT: [[R:%.*]] = fpext float [[F]] to double 299; CHECK-NEXT: ret double [[R]] 300; 301 %f = sitofp i32 %x to float 302 %r = fpext float %f to double 303 ret double %r 304} 305 306define double @masked_sint_to_fpext1(i32 %x) { 307; CHECK-LABEL: @masked_sint_to_fpext1( 308; CHECK-NEXT: [[M:%.*]] = and i32 [[X:%.*]], 16777215 309; CHECK-NEXT: [[R:%.*]] = uitofp nneg i32 [[M]] to double 310; CHECK-NEXT: ret double [[R]] 311; 312 %m = and i32 %x, 16777215 313 %f = sitofp i32 %m to float 314 %r = fpext float %f to double 315 ret double %r 316} 317 318define double @masked_sint_to_fpext2(i32 %x) { 319; CHECK-LABEL: @masked_sint_to_fpext2( 320; CHECK-NEXT: [[M:%.*]] = lshr i32 [[X:%.*]], 8 321; CHECK-NEXT: [[R:%.*]] = uitofp nneg i32 [[M]] to double 322; CHECK-NEXT: ret double [[R]] 323; 324 %m = lshr i32 %x, 8 325 %f = sitofp i32 %m to float 326 %r = fpext float %f to double 327 ret double %r 328} 329 330define double @masked_sint_to_fpext3(i32 %x) { 331; CHECK-LABEL: @masked_sint_to_fpext3( 332; CHECK-NEXT: [[M:%.*]] = lshr i32 [[X:%.*]], 7 333; CHECK-NEXT: [[F:%.*]] = uitofp nneg i32 [[M]] to float 334; CHECK-NEXT: [[R:%.*]] = fpext float [[F]] to double 335; CHECK-NEXT: ret double [[R]] 336; 337 %m = lshr i32 %x, 7 338 %f = sitofp i32 %m to float 339 %r = fpext float %f to double 340 ret double %r 341} 342 343define half @uint_to_fptrunc(i32 %x) { 344; CHECK-LABEL: @uint_to_fptrunc( 345; CHECK-NEXT: [[F:%.*]] = uitofp i32 [[X:%.*]] to float 346; CHECK-NEXT: [[R:%.*]] = fptrunc float [[F]] to half 347; CHECK-NEXT: ret half [[R]] 348; 349 %f = uitofp i32 %x to float 350 %r = fptrunc float %f to half 351 ret half %r 352} 353 354define half @masked_uint_to_fptrunc1(i32 %x) { 355; CHECK-LABEL: @masked_uint_to_fptrunc1( 356; CHECK-NEXT: [[M:%.*]] = and i32 [[X:%.*]], 16777215 357; CHECK-NEXT: [[R:%.*]] = uitofp nneg i32 [[M]] to half 358; CHECK-NEXT: ret half [[R]] 359; 360 %m = and i32 %x, 16777215 361 %f = uitofp i32 %m to float 362 %r = fptrunc float %f to half 363 ret half %r 364} 365 366define half @masked_uint_to_fptrunc2(i32 %x) { 367; CHECK-LABEL: @masked_uint_to_fptrunc2( 368; CHECK-NEXT: [[M:%.*]] = lshr i32 [[X:%.*]], 8 369; CHECK-NEXT: [[R:%.*]] = uitofp nneg i32 [[M]] to half 370; CHECK-NEXT: ret half [[R]] 371; 372 %m = lshr i32 %x, 8 373 %f = uitofp i32 %m to float 374 %r = fptrunc float %f to half 375 ret half %r 376} 377 378define half @masked_uint_to_fptrunc3(i32 %x) { 379; CHECK-LABEL: @masked_uint_to_fptrunc3( 380; CHECK-NEXT: [[M:%.*]] = lshr i32 [[X:%.*]], 7 381; CHECK-NEXT: [[F:%.*]] = uitofp nneg i32 [[M]] to float 382; CHECK-NEXT: [[R:%.*]] = fptrunc float [[F]] to half 383; CHECK-NEXT: ret half [[R]] 384; 385 %m = lshr i32 %x, 7 386 %f = uitofp i32 %m to float 387 %r = fptrunc float %f to half 388 ret half %r 389} 390 391define double @uint_to_fpext(i32 %x) { 392; CHECK-LABEL: @uint_to_fpext( 393; CHECK-NEXT: [[F:%.*]] = uitofp i32 [[X:%.*]] to float 394; CHECK-NEXT: [[R:%.*]] = fpext float [[F]] to double 395; CHECK-NEXT: ret double [[R]] 396; 397 %f = uitofp i32 %x to float 398 %r = fpext float %f to double 399 ret double %r 400} 401 402define double @masked_uint_to_fpext1(i32 %x) { 403; CHECK-LABEL: @masked_uint_to_fpext1( 404; CHECK-NEXT: [[M:%.*]] = and i32 [[X:%.*]], 16777215 405; CHECK-NEXT: [[R:%.*]] = uitofp nneg i32 [[M]] to double 406; CHECK-NEXT: ret double [[R]] 407; 408 %m = and i32 %x, 16777215 409 %f = uitofp i32 %m to float 410 %r = fpext float %f to double 411 ret double %r 412} 413 414define double @masked_uint_to_fpext2(i32 %x) { 415; CHECK-LABEL: @masked_uint_to_fpext2( 416; CHECK-NEXT: [[M:%.*]] = lshr i32 [[X:%.*]], 8 417; CHECK-NEXT: [[R:%.*]] = uitofp nneg i32 [[M]] to double 418; CHECK-NEXT: ret double [[R]] 419; 420 %m = lshr i32 %x, 8 421 %f = uitofp i32 %m to float 422 %r = fpext float %f to double 423 ret double %r 424} 425 426define double @masked_uint_to_fpext3(i32 %x) { 427; CHECK-LABEL: @masked_uint_to_fpext3( 428; CHECK-NEXT: [[M:%.*]] = lshr i32 [[X:%.*]], 7 429; CHECK-NEXT: [[F:%.*]] = uitofp nneg i32 [[M]] to float 430; CHECK-NEXT: [[R:%.*]] = fpext float [[F]] to double 431; CHECK-NEXT: ret double [[R]] 432; 433 %m = lshr i32 %x, 7 434 %f = uitofp i32 %m to float 435 %r = fpext float %f to double 436 ret double %r 437} 438 439define i32 @fptosi_nonnorm(float nofpclass(norm) %x) { 440; CHECK-LABEL: @fptosi_nonnorm( 441; CHECK-NEXT: ret i32 0 442; 443 %ret = fptosi float %x to i32 444 ret i32 %ret 445} 446 447define i32 @fptoui_nonnorm(float nofpclass(pnorm) %x) { 448; CHECK-LABEL: @fptoui_nonnorm( 449; CHECK-NEXT: ret i32 0 450; 451 %ret = fptoui float %x to i32 452 ret i32 %ret 453} 454 455define i32 @fptosi_nonnnorm(float nofpclass(nnorm) %x) { 456; CHECK-LABEL: @fptosi_nonnnorm( 457; CHECK-NEXT: [[RET:%.*]] = fptosi float [[X:%.*]] to i32 458; CHECK-NEXT: ret i32 [[RET]] 459; 460 %ret = fptosi float %x to i32 461 ret i32 %ret 462} 463 464define i32 @fptoui_nonnnorm(float nofpclass(nnorm) %x) { 465; CHECK-LABEL: @fptoui_nonnnorm( 466; CHECK-NEXT: [[RET:%.*]] = fptoui float [[X:%.*]] to i32 467; CHECK-NEXT: ret i32 [[RET]] 468; 469 %ret = fptoui float %x to i32 470 ret i32 %ret 471} 472 473define i32 @fptosi_nonnorm_copysign(float %x) { 474; CHECK-LABEL: @fptosi_nonnorm_copysign( 475; CHECK-NEXT: ret i32 0 476; 477 %val = call float @llvm.copysign.f32(float 0.0, float %x) 478 %ret = fptosi float %val to i32 479 ret i32 %ret 480} 481 482define <2 x i32> @fptosi_nonnorm_copysign_vec(<2 x float> %x) { 483; CHECK-LABEL: @fptosi_nonnorm_copysign_vec( 484; CHECK-NEXT: ret <2 x i32> zeroinitializer 485; 486 %val = call <2 x float> @llvm.copysign.v2f32(<2 x float> zeroinitializer, <2 x float> %x) 487 %ret = fptosi <2 x float> %val to <2 x i32> 488 ret <2 x i32> %ret 489} 490 491define i32 @fptosi_nonnorm_fmul(float %x) { 492; CHECK-LABEL: @fptosi_nonnorm_fmul( 493; CHECK-NEXT: [[SEL:%.*]] = fmul float [[X:%.*]], 0.000000e+00 494; CHECK-NEXT: [[RET:%.*]] = fptosi float [[SEL]] to i32 495; CHECK-NEXT: ret i32 [[RET]] 496; 497 %sel = fmul float %x, 0.000000e+00 498 %ret = fptosi float %sel to i32 499 ret i32 %ret 500} 501 502define i32 @fptosi_select(i1 %cond) { 503; CHECK-LABEL: @fptosi_select( 504; CHECK-NEXT: [[RET:%.*]] = select i1 [[COND:%.*]], i32 1, i32 -1 505; CHECK-NEXT: ret i32 [[RET]] 506; 507 %sel = select i1 %cond, float 1.0, float -1.0 508 %ret = fptosi float %sel to i32 509 ret i32 %ret 510} 511 512define i32 @mul_pos_zero_convert(i32 %a) { 513; CHECK-LABEL: @mul_pos_zero_convert( 514; CHECK-NEXT: entry: 515; CHECK-NEXT: ret i32 0 516; 517entry: 518 %fp = sitofp i32 %a to float 519 %ret = fmul float %fp, 0.000000e+00 520 %conv = fptosi float %ret to i32 521 ret i32 %conv 522} 523