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 @fneg_fptrunc(float %a) { 33; CHECK-LABEL: @fneg_fptrunc( 34; CHECK-NEXT: [[TMP1:%.*]] = fptrunc float [[A:%.*]] to half 35; CHECK-NEXT: [[C:%.*]] = fneg half [[TMP1]] 36; CHECK-NEXT: ret half [[C]] 37; 38 %b = fsub float -0.0, %a 39 %c = fptrunc float %b to half 40 ret half %c 41} 42 43define half @unary_fneg_fptrunc(float %a) { 44; CHECK-LABEL: @unary_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 = fneg float %a 50 %c = fptrunc float %b to half 51 ret half %c 52} 53 54define <2 x half> @fneg_fptrunc_vec_poison(<2 x float> %a) { 55; CHECK-LABEL: @fneg_fptrunc_vec_poison( 56; CHECK-NEXT: [[TMP1:%.*]] = fptrunc <2 x float> [[A:%.*]] to <2 x half> 57; CHECK-NEXT: [[C:%.*]] = fneg <2 x half> [[TMP1]] 58; CHECK-NEXT: ret <2 x half> [[C]] 59; 60 %b = fsub <2 x float> <float -0.0, float poison>, %a 61 %c = fptrunc <2 x float> %b to <2 x half> 62 ret <2 x half> %c 63} 64 65define <2 x half> @unary_fneg_fptrunc_vec(<2 x float> %a) { 66; CHECK-LABEL: @unary_fneg_fptrunc_vec( 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 = fneg <2 x float> %a 72 %c = fptrunc <2 x float> %b to <2 x half> 73 ret <2 x half> %c 74} 75 76define half @test4-fast(float %a) { 77; CHECK-LABEL: @test4-fast( 78; CHECK-NEXT: [[TMP1:%.*]] = fptrunc fast float [[A:%.*]] to half 79; CHECK-NEXT: [[C:%.*]] = fneg fast half [[TMP1]] 80; CHECK-NEXT: ret half [[C]] 81; 82 %b = fsub fast float -0.0, %a 83 %c = fptrunc float %b to half 84 ret half %c 85} 86 87define half @test4_unary_fneg-fast(float %a) { 88; CHECK-LABEL: @test4_unary_fneg-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 = fneg fast float %a 94 %c = fptrunc float %b to half 95 ret half %c 96} 97 98define half @test5(float %a, float %b, float %c) { 99; CHECK-LABEL: @test5( 100; CHECK-NEXT: [[D:%.*]] = fcmp ogt float [[A:%.*]], [[B:%.*]] 101; CHECK-NEXT: [[E:%.*]] = select i1 [[D]], float [[C:%.*]], float 1.000000e+00 102; CHECK-NEXT: [[F:%.*]] = fptrunc float [[E]] to half 103; CHECK-NEXT: ret half [[F]] 104; 105 %d = fcmp ogt float %a, %b 106 %e = select i1 %d, float %c, float 1.0 107 %f = fptrunc float %e to half 108 ret half %f 109} 110 111declare float @llvm.fabs.f32(float) nounwind readonly 112 113define <1 x float> @test6(<1 x double> %V) { 114; CHECK-LABEL: @test6( 115; CHECK-NEXT: [[FREM:%.*]] = frem <1 x double> [[V:%.*]], [[V]] 116; CHECK-NEXT: [[TRUNC:%.*]] = fptrunc <1 x double> [[FREM]] to <1 x float> 117; CHECK-NEXT: ret <1 x float> [[TRUNC]] 118; 119 %frem = frem <1 x double> %V, %V 120 %trunc = fptrunc <1 x double> %frem to <1 x float> 121 ret <1 x float> %trunc 122} 123 124define float @test7(double %V) { 125; CHECK-LABEL: @test7( 126; CHECK-NEXT: [[FREM:%.*]] = frem double [[V:%.*]], 1.000000e+00 127; CHECK-NEXT: [[TRUNC:%.*]] = fptrunc double [[FREM]] to float 128; CHECK-NEXT: ret float [[TRUNC]] 129; 130 %frem = frem double %V, 1.000000e+00 131 %trunc = fptrunc double %frem to float 132 ret float %trunc 133} 134 135define float @test8(float %V) { 136; CHECK-LABEL: @test8( 137; CHECK-NEXT: [[FEXT:%.*]] = fpext float [[V:%.*]] to double 138; CHECK-NEXT: [[FREM:%.*]] = frem double [[FEXT]], 1.000000e-01 139; CHECK-NEXT: [[TRUNC:%.*]] = fptrunc double [[FREM]] to float 140; CHECK-NEXT: ret float [[TRUNC]] 141; 142 %fext = fpext float %V to double 143 %frem = frem double %fext, 1.000000e-01 144 %trunc = fptrunc double %frem to float 145 ret float %trunc 146} 147 148define half @test_fptrunc_fptrunc(double %V) { 149; CHECK-LABEL: @test_fptrunc_fptrunc( 150; CHECK-NEXT: [[T1:%.*]] = fptrunc double [[V:%.*]] to float 151; CHECK-NEXT: [[T2:%.*]] = fptrunc float [[T1]] to half 152; CHECK-NEXT: ret half [[T2]] 153; 154 %t1 = fptrunc double %V to float 155 %t2 = fptrunc float %t1 to half 156 ret half %t2 157} 158 159define half @sint_to_fptrunc(i32 %x) { 160; CHECK-LABEL: @sint_to_fptrunc( 161; CHECK-NEXT: [[F:%.*]] = sitofp i32 [[X:%.*]] to float 162; CHECK-NEXT: [[R:%.*]] = fptrunc float [[F]] to half 163; CHECK-NEXT: ret half [[R]] 164; 165 %f = sitofp i32 %x to float 166 %r = fptrunc float %f to half 167 ret half %r 168} 169 170define half @masked_sint_to_fptrunc1(i32 %x) { 171; CHECK-LABEL: @masked_sint_to_fptrunc1( 172; CHECK-NEXT: [[M:%.*]] = and i32 [[X:%.*]], 16777215 173; CHECK-NEXT: [[R:%.*]] = uitofp nneg i32 [[M]] to half 174; CHECK-NEXT: ret half [[R]] 175; 176 %m = and i32 %x, 16777215 177 %f = sitofp i32 %m to float 178 %r = fptrunc float %f to half 179 ret half %r 180} 181 182define half @masked_sint_to_fptrunc2(i32 %x) { 183; CHECK-LABEL: @masked_sint_to_fptrunc2( 184; CHECK-NEXT: [[M:%.*]] = lshr i32 [[X:%.*]], 8 185; CHECK-NEXT: [[R:%.*]] = uitofp nneg i32 [[M]] to half 186; CHECK-NEXT: ret half [[R]] 187; 188 %m = lshr i32 %x, 8 189 %f = sitofp i32 %m to float 190 %r = fptrunc float %f to half 191 ret half %r 192} 193 194define half @masked_sint_to_fptrunc3(i32 %x) { 195; CHECK-LABEL: @masked_sint_to_fptrunc3( 196; CHECK-NEXT: [[M:%.*]] = lshr i32 [[X:%.*]], 7 197; CHECK-NEXT: [[F:%.*]] = uitofp nneg i32 [[M]] to float 198; CHECK-NEXT: [[R:%.*]] = fptrunc float [[F]] to half 199; CHECK-NEXT: ret half [[R]] 200; 201 %m = lshr i32 %x, 7 202 %f = sitofp i32 %m to float 203 %r = fptrunc float %f to half 204 ret half %r 205} 206 207define double @sint_to_fpext(i32 %x) { 208; CHECK-LABEL: @sint_to_fpext( 209; CHECK-NEXT: [[F:%.*]] = sitofp i32 [[X:%.*]] to float 210; CHECK-NEXT: [[R:%.*]] = fpext float [[F]] to double 211; CHECK-NEXT: ret double [[R]] 212; 213 %f = sitofp i32 %x to float 214 %r = fpext float %f to double 215 ret double %r 216} 217 218define double @masked_sint_to_fpext1(i32 %x) { 219; CHECK-LABEL: @masked_sint_to_fpext1( 220; CHECK-NEXT: [[M:%.*]] = and i32 [[X:%.*]], 16777215 221; CHECK-NEXT: [[R:%.*]] = uitofp nneg i32 [[M]] to double 222; CHECK-NEXT: ret double [[R]] 223; 224 %m = and i32 %x, 16777215 225 %f = sitofp i32 %m to float 226 %r = fpext float %f to double 227 ret double %r 228} 229 230define double @masked_sint_to_fpext2(i32 %x) { 231; CHECK-LABEL: @masked_sint_to_fpext2( 232; CHECK-NEXT: [[M:%.*]] = lshr i32 [[X:%.*]], 8 233; CHECK-NEXT: [[R:%.*]] = uitofp nneg i32 [[M]] to double 234; CHECK-NEXT: ret double [[R]] 235; 236 %m = lshr i32 %x, 8 237 %f = sitofp i32 %m to float 238 %r = fpext float %f to double 239 ret double %r 240} 241 242define double @masked_sint_to_fpext3(i32 %x) { 243; CHECK-LABEL: @masked_sint_to_fpext3( 244; CHECK-NEXT: [[M:%.*]] = lshr i32 [[X:%.*]], 7 245; CHECK-NEXT: [[F:%.*]] = uitofp nneg i32 [[M]] to float 246; CHECK-NEXT: [[R:%.*]] = fpext float [[F]] to double 247; CHECK-NEXT: ret double [[R]] 248; 249 %m = lshr i32 %x, 7 250 %f = sitofp i32 %m to float 251 %r = fpext float %f to double 252 ret double %r 253} 254 255define half @uint_to_fptrunc(i32 %x) { 256; CHECK-LABEL: @uint_to_fptrunc( 257; CHECK-NEXT: [[F:%.*]] = uitofp i32 [[X:%.*]] to float 258; CHECK-NEXT: [[R:%.*]] = fptrunc float [[F]] to half 259; CHECK-NEXT: ret half [[R]] 260; 261 %f = uitofp i32 %x to float 262 %r = fptrunc float %f to half 263 ret half %r 264} 265 266define half @masked_uint_to_fptrunc1(i32 %x) { 267; CHECK-LABEL: @masked_uint_to_fptrunc1( 268; CHECK-NEXT: [[M:%.*]] = and i32 [[X:%.*]], 16777215 269; CHECK-NEXT: [[R:%.*]] = uitofp nneg i32 [[M]] to half 270; CHECK-NEXT: ret half [[R]] 271; 272 %m = and i32 %x, 16777215 273 %f = uitofp i32 %m to float 274 %r = fptrunc float %f to half 275 ret half %r 276} 277 278define half @masked_uint_to_fptrunc2(i32 %x) { 279; CHECK-LABEL: @masked_uint_to_fptrunc2( 280; CHECK-NEXT: [[M:%.*]] = lshr i32 [[X:%.*]], 8 281; CHECK-NEXT: [[R:%.*]] = uitofp nneg i32 [[M]] to half 282; CHECK-NEXT: ret half [[R]] 283; 284 %m = lshr i32 %x, 8 285 %f = uitofp i32 %m to float 286 %r = fptrunc float %f to half 287 ret half %r 288} 289 290define half @masked_uint_to_fptrunc3(i32 %x) { 291; CHECK-LABEL: @masked_uint_to_fptrunc3( 292; CHECK-NEXT: [[M:%.*]] = lshr i32 [[X:%.*]], 7 293; CHECK-NEXT: [[F:%.*]] = uitofp nneg i32 [[M]] to float 294; CHECK-NEXT: [[R:%.*]] = fptrunc float [[F]] to half 295; CHECK-NEXT: ret half [[R]] 296; 297 %m = lshr i32 %x, 7 298 %f = uitofp i32 %m to float 299 %r = fptrunc float %f to half 300 ret half %r 301} 302 303define double @uint_to_fpext(i32 %x) { 304; CHECK-LABEL: @uint_to_fpext( 305; CHECK-NEXT: [[F:%.*]] = uitofp i32 [[X:%.*]] to float 306; CHECK-NEXT: [[R:%.*]] = fpext float [[F]] to double 307; CHECK-NEXT: ret double [[R]] 308; 309 %f = uitofp i32 %x to float 310 %r = fpext float %f to double 311 ret double %r 312} 313 314define double @masked_uint_to_fpext1(i32 %x) { 315; CHECK-LABEL: @masked_uint_to_fpext1( 316; CHECK-NEXT: [[M:%.*]] = and i32 [[X:%.*]], 16777215 317; CHECK-NEXT: [[R:%.*]] = uitofp nneg i32 [[M]] to double 318; CHECK-NEXT: ret double [[R]] 319; 320 %m = and i32 %x, 16777215 321 %f = uitofp i32 %m to float 322 %r = fpext float %f to double 323 ret double %r 324} 325 326define double @masked_uint_to_fpext2(i32 %x) { 327; CHECK-LABEL: @masked_uint_to_fpext2( 328; CHECK-NEXT: [[M:%.*]] = lshr i32 [[X:%.*]], 8 329; CHECK-NEXT: [[R:%.*]] = uitofp nneg i32 [[M]] to double 330; CHECK-NEXT: ret double [[R]] 331; 332 %m = lshr i32 %x, 8 333 %f = uitofp i32 %m to float 334 %r = fpext float %f to double 335 ret double %r 336} 337 338define double @masked_uint_to_fpext3(i32 %x) { 339; CHECK-LABEL: @masked_uint_to_fpext3( 340; CHECK-NEXT: [[M:%.*]] = lshr i32 [[X:%.*]], 7 341; CHECK-NEXT: [[F:%.*]] = uitofp nneg i32 [[M]] to float 342; CHECK-NEXT: [[R:%.*]] = fpext float [[F]] to double 343; CHECK-NEXT: ret double [[R]] 344; 345 %m = lshr i32 %x, 7 346 %f = uitofp i32 %m to float 347 %r = fpext float %f to double 348 ret double %r 349} 350 351define i32 @fptosi_nonnorm(float nofpclass(norm) %x) { 352; CHECK-LABEL: @fptosi_nonnorm( 353; CHECK-NEXT: ret i32 0 354; 355 %ret = fptosi float %x to i32 356 ret i32 %ret 357} 358 359define i32 @fptoui_nonnorm(float nofpclass(pnorm) %x) { 360; CHECK-LABEL: @fptoui_nonnorm( 361; CHECK-NEXT: ret i32 0 362; 363 %ret = fptoui float %x to i32 364 ret i32 %ret 365} 366 367define i32 @fptosi_nonnnorm(float nofpclass(nnorm) %x) { 368; CHECK-LABEL: @fptosi_nonnnorm( 369; CHECK-NEXT: [[RET:%.*]] = fptosi float [[X:%.*]] to i32 370; CHECK-NEXT: ret i32 [[RET]] 371; 372 %ret = fptosi float %x to i32 373 ret i32 %ret 374} 375 376define i32 @fptoui_nonnnorm(float nofpclass(nnorm) %x) { 377; CHECK-LABEL: @fptoui_nonnnorm( 378; CHECK-NEXT: [[RET:%.*]] = fptoui float [[X:%.*]] to i32 379; CHECK-NEXT: ret i32 [[RET]] 380; 381 %ret = fptoui float %x to i32 382 ret i32 %ret 383} 384 385define i32 @fptosi_nonnorm_copysign(float %x) { 386; CHECK-LABEL: @fptosi_nonnorm_copysign( 387; CHECK-NEXT: ret i32 0 388; 389 %val = call float @llvm.copysign.f32(float 0.0, float %x) 390 %ret = fptosi float %val to i32 391 ret i32 %ret 392} 393 394define <2 x i32> @fptosi_nonnorm_copysign_vec(<2 x float> %x) { 395; CHECK-LABEL: @fptosi_nonnorm_copysign_vec( 396; CHECK-NEXT: ret <2 x i32> zeroinitializer 397; 398 %val = call <2 x float> @llvm.copysign.v2f32(<2 x float> zeroinitializer, <2 x float> %x) 399 %ret = fptosi <2 x float> %val to <2 x i32> 400 ret <2 x i32> %ret 401} 402 403define i32 @fptosi_nonnorm_fmul(float %x) { 404; CHECK-LABEL: @fptosi_nonnorm_fmul( 405; CHECK-NEXT: [[SEL:%.*]] = fmul float [[X:%.*]], 0.000000e+00 406; CHECK-NEXT: [[RET:%.*]] = fptosi float [[SEL]] to i32 407; CHECK-NEXT: ret i32 [[RET]] 408; 409 %sel = fmul float %x, 0.000000e+00 410 %ret = fptosi float %sel to i32 411 ret i32 %ret 412} 413 414define i32 @fptosi_select(i1 %cond) { 415; CHECK-LABEL: @fptosi_select( 416; CHECK-NEXT: [[RET:%.*]] = select i1 [[COND:%.*]], i32 1, i32 -1 417; CHECK-NEXT: ret i32 [[RET]] 418; 419 %sel = select i1 %cond, float 1.0, float -1.0 420 %ret = fptosi float %sel to i32 421 ret i32 %ret 422} 423 424define i32 @mul_pos_zero_convert(i32 %a) { 425; CHECK-LABEL: @mul_pos_zero_convert( 426; CHECK-NEXT: entry: 427; CHECK-NEXT: ret i32 0 428; 429entry: 430 %fp = sitofp i32 %a to float 431 %ret = fmul float %fp, 0.000000e+00 432 %conv = fptosi float %ret to i32 433 ret i32 %conv 434} 435