1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4define float @test(float %x) nounwind { 5; CHECK-LABEL: @test( 6; CHECK-NEXT: [[T34:%.*]] = fadd float [[X:%.*]], 0.000000e+00 7; CHECK-NEXT: ret float [[T34]] 8; 9 %t1 = fpext float %x to double 10 %t3 = fadd double %t1, 0.000000e+00 11 %t34 = fptrunc double %t3 to float 12 ret float %t34 13} 14 15define float @test2(float %x, float %y) nounwind { 16; CHECK-LABEL: @test2( 17; CHECK-NEXT: [[T56:%.*]] = fmul float [[X:%.*]], [[Y:%.*]] 18; CHECK-NEXT: ret float [[T56]] 19; 20 %t1 = fpext float %x to double 21 %t23 = fpext float %y to double 22 %t5 = fmul double %t1, %t23 23 %t56 = fptrunc double %t5 to float 24 ret float %t56 25} 26 27define float @test3(float %x, float %y) nounwind { 28; CHECK-LABEL: @test3( 29; CHECK-NEXT: [[T56:%.*]] = fdiv float [[X:%.*]], [[Y:%.*]] 30; CHECK-NEXT: ret float [[T56]] 31; 32 %t1 = fpext float %x to double 33 %t23 = fpext float %y to double 34 %t5 = fdiv double %t1, %t23 35 %t56 = fptrunc double %t5 to float 36 ret float %t56 37} 38 39define float @test4(float %x) nounwind { 40; CHECK-LABEL: @test4( 41; CHECK-NEXT: [[T34:%.*]] = fneg float [[X:%.*]] 42; CHECK-NEXT: ret float [[T34]] 43; 44 %t1 = fpext float %x to double 45 %t2 = fsub double -0.000000e+00, %t1 46 %t34 = fptrunc double %t2 to float 47 ret float %t34 48} 49 50define float @test4_unary_fneg(float %x) nounwind { 51; CHECK-LABEL: @test4_unary_fneg( 52; CHECK-NEXT: [[T34:%.*]] = fneg float [[X:%.*]] 53; CHECK-NEXT: ret float [[T34]] 54; 55 %t1 = fpext float %x to double 56 %t2 = fneg double %t1 57 %t34 = fptrunc double %t2 to float 58 ret float %t34 59} 60 61; Test with vector splat constant 62define <2 x float> @test5(<2 x float> %x) nounwind { 63; CHECK-LABEL: @test5( 64; CHECK-NEXT: [[T34:%.*]] = fadd <2 x float> [[X:%.*]], zeroinitializer 65; CHECK-NEXT: ret <2 x float> [[T34]] 66; 67 %t1 = fpext <2 x float> %x to <2 x double> 68 %t3 = fadd <2 x double> %t1, <double 0.000000e+00, double 0.000000e+00> 69 %t34 = fptrunc <2 x double> %t3 to <2 x float> 70 ret <2 x float> %t34 71} 72 73; Test with a non-splat constant 74define <2 x float> @test6(<2 x float> %x) nounwind { 75; CHECK-LABEL: @test6( 76; CHECK-NEXT: [[T34:%.*]] = fadd <2 x float> [[X:%.*]], <float 0.000000e+00, float -0.000000e+00> 77; CHECK-NEXT: ret <2 x float> [[T34]] 78; 79 %t1 = fpext <2 x float> %x to <2 x double> 80 %t3 = fadd <2 x double> %t1, <double 0.000000e+00, double -0.000000e+00> 81 %t34 = fptrunc <2 x double> %t3 to <2 x float> 82 ret <2 x float> %t34 83} 84 85; Test with an undef element 86define <2 x float> @test6_undef(<2 x float> %x) nounwind { 87; CHECK-LABEL: @test6_undef( 88; CHECK-NEXT: [[T34:%.*]] = fadd <2 x float> [[X:%.*]], <float 0.000000e+00, float undef> 89; CHECK-NEXT: ret <2 x float> [[T34]] 90; 91 %t1 = fpext <2 x float> %x to <2 x double> 92 %t3 = fadd <2 x double> %t1, <double 0.000000e+00, double undef> 93 %t34 = fptrunc <2 x double> %t3 to <2 x float> 94 ret <2 x float> %t34 95} 96 97define <2 x float> @not_half_shrinkable(<2 x float> %x) { 98; CHECK-LABEL: @not_half_shrinkable( 99; CHECK-NEXT: [[R:%.*]] = fadd <2 x float> [[X:%.*]], <float 0.000000e+00, float 2.049000e+03> 100; CHECK-NEXT: ret <2 x float> [[R]] 101; 102 %ext = fpext <2 x float> %x to <2 x double> 103 %add = fadd <2 x double> %ext, <double 0.0, double 2049.0> 104 %r = fptrunc <2 x double> %add to <2 x float> 105 ret <2 x float> %r 106} 107 108define half @test7(float %a) nounwind { 109; CHECK-LABEL: @test7( 110; CHECK-NEXT: [[Z:%.*]] = fptrunc float [[A:%.*]] to half 111; CHECK-NEXT: ret half [[Z]] 112; 113 %y = fpext float %a to double 114 %z = fptrunc double %y to half 115 ret half %z 116} 117 118define float @test8(half %a) nounwind { 119; CHECK-LABEL: @test8( 120; CHECK-NEXT: [[Z:%.*]] = fpext half [[A:%.*]] to float 121; CHECK-NEXT: ret float [[Z]] 122; 123 %y = fpext half %a to double 124 %z = fptrunc double %y to float 125 ret float %z 126} 127 128define float @test9(half %x, half %y) nounwind { 129; CHECK-LABEL: @test9( 130; CHECK-NEXT: [[TMP1:%.*]] = fpext half [[X:%.*]] to float 131; CHECK-NEXT: [[TMP2:%.*]] = fpext half [[Y:%.*]] to float 132; CHECK-NEXT: [[T56:%.*]] = fmul float [[TMP1]], [[TMP2]] 133; CHECK-NEXT: ret float [[T56]] 134; 135 %t1 = fpext half %x to double 136 %t23 = fpext half %y to double 137 %t5 = fmul double %t1, %t23 138 %t56 = fptrunc double %t5 to float 139 ret float %t56 140} 141 142define float @test10(half %x, float %y) nounwind { 143; CHECK-LABEL: @test10( 144; CHECK-NEXT: [[TMP1:%.*]] = fpext half [[X:%.*]] to float 145; CHECK-NEXT: [[T56:%.*]] = fmul float [[Y:%.*]], [[TMP1]] 146; CHECK-NEXT: ret float [[T56]] 147; 148 %t1 = fpext half %x to double 149 %t23 = fpext float %y to double 150 %t5 = fmul double %t1, %t23 151 %t56 = fptrunc double %t5 to float 152 ret float %t56 153} 154 155define float @test11(half %x) nounwind { 156; CHECK-LABEL: @test11( 157; CHECK-NEXT: [[TMP1:%.*]] = fpext half [[X:%.*]] to float 158; CHECK-NEXT: [[T34:%.*]] = fadd float [[TMP1]], 0.000000e+00 159; CHECK-NEXT: ret float [[T34]] 160; 161 %t1 = fpext half %x to double 162 %t3 = fadd double %t1, 0.000000e+00 163 %t34 = fptrunc double %t3 to float 164 ret float %t34 165} 166 167define float @test12(float %x, half %y) nounwind { 168; CHECK-LABEL: @test12( 169; CHECK-NEXT: [[TMP1:%.*]] = fpext half [[Y:%.*]] to float 170; CHECK-NEXT: [[T34:%.*]] = fadd float [[X:%.*]], [[TMP1]] 171; CHECK-NEXT: ret float [[T34]] 172; 173 %t1 = fpext float %x to double 174 %t2 = fpext half %y to double 175 %t3 = fadd double %t1, %t2 176 %t34 = fptrunc double %t3 to float 177 ret float %t34 178} 179 180define float @test13(half %x, float %y) nounwind { 181; CHECK-LABEL: @test13( 182; CHECK-NEXT: [[TMP1:%.*]] = fpext half [[X:%.*]] to float 183; CHECK-NEXT: [[T56:%.*]] = fdiv float [[TMP1]], [[Y:%.*]] 184; CHECK-NEXT: ret float [[T56]] 185; 186 %t1 = fpext half %x to double 187 %t23 = fpext float %y to double 188 %t5 = fdiv double %t1, %t23 189 %t56 = fptrunc double %t5 to float 190 ret float %t56 191} 192 193define float @test14(float %x, half %y) nounwind { 194; CHECK-LABEL: @test14( 195; CHECK-NEXT: [[TMP1:%.*]] = fpext half [[Y:%.*]] to float 196; CHECK-NEXT: [[T56:%.*]] = fdiv float [[X:%.*]], [[TMP1]] 197; CHECK-NEXT: ret float [[T56]] 198; 199 %t1 = fpext float %x to double 200 %t23 = fpext half %y to double 201 %t5 = fdiv double %t1, %t23 202 %t56 = fptrunc double %t5 to float 203 ret float %t56 204} 205 206define float @test15(half %x, half %y) nounwind { 207; CHECK-LABEL: @test15( 208; CHECK-NEXT: [[TMP1:%.*]] = fpext half [[X:%.*]] to float 209; CHECK-NEXT: [[TMP2:%.*]] = fpext half [[Y:%.*]] to float 210; CHECK-NEXT: [[T56:%.*]] = fdiv float [[TMP1]], [[TMP2]] 211; CHECK-NEXT: ret float [[T56]] 212; 213 %t1 = fpext half %x to double 214 %t23 = fpext half %y to double 215 %t5 = fdiv double %t1, %t23 216 %t56 = fptrunc double %t5 to float 217 ret float %t56 218} 219 220define float @test16(half %x, float %y) nounwind { 221; CHECK-LABEL: @test16( 222; CHECK-NEXT: [[TMP1:%.*]] = fpext half [[X:%.*]] to float 223; CHECK-NEXT: [[TMP2:%.*]] = frem float [[TMP1]], [[Y:%.*]] 224; CHECK-NEXT: ret float [[TMP2]] 225; 226 %t1 = fpext half %x to double 227 %t23 = fpext float %y to double 228 %t5 = frem double %t1, %t23 229 %t56 = fptrunc double %t5 to float 230 ret float %t56 231} 232 233define float @test17(float %x, half %y) nounwind { 234; CHECK-LABEL: @test17( 235; CHECK-NEXT: [[TMP1:%.*]] = fpext half [[Y:%.*]] to float 236; CHECK-NEXT: [[TMP2:%.*]] = frem float [[X:%.*]], [[TMP1]] 237; CHECK-NEXT: ret float [[TMP2]] 238; 239 %t1 = fpext float %x to double 240 %t23 = fpext half %y to double 241 %t5 = frem double %t1, %t23 242 %t56 = fptrunc double %t5 to float 243 ret float %t56 244} 245 246define float @test18(half %x, half %y) nounwind { 247; CHECK-LABEL: @test18( 248; CHECK-NEXT: [[TMP1:%.*]] = frem half [[X:%.*]], [[Y:%.*]] 249; CHECK-NEXT: [[T56:%.*]] = fpext half [[TMP1]] to float 250; CHECK-NEXT: ret float [[T56]] 251; 252 %t1 = fpext half %x to double 253 %t23 = fpext half %y to double 254 %t5 = frem double %t1, %t23 255 %t56 = fptrunc double %t5 to float 256 ret float %t56 257} 258 259; Convert from integer is exact, so convert directly to double. 260 261define double @ItoFtoF_s25_f32_f64(i25 %i) { 262; CHECK-LABEL: @ItoFtoF_s25_f32_f64( 263; CHECK-NEXT: [[R:%.*]] = sitofp i25 [[I:%.*]] to double 264; CHECK-NEXT: ret double [[R]] 265; 266 %x = sitofp i25 %i to float 267 %r = fpext float %x to double 268 ret double %r 269} 270 271; Convert from integer is exact, so convert directly to fp128. 272 273define fp128 @ItoFtoF_u24_f32_f128(i24 %i) { 274; CHECK-LABEL: @ItoFtoF_u24_f32_f128( 275; CHECK-NEXT: [[R:%.*]] = uitofp i24 [[I:%.*]] to fp128 276; CHECK-NEXT: ret fp128 [[R]] 277; 278 %x = uitofp i24 %i to float 279 %r = fpext float %x to fp128 280 ret fp128 %r 281} 282 283; Negative test - intermediate rounding in float type. 284 285define double @ItoFtoF_s26_f32_f64(i26 %i) { 286; CHECK-LABEL: @ItoFtoF_s26_f32_f64( 287; CHECK-NEXT: [[X:%.*]] = sitofp i26 [[I:%.*]] to float 288; CHECK-NEXT: [[R:%.*]] = fpext float [[X]] to double 289; CHECK-NEXT: ret double [[R]] 290; 291 %x = sitofp i26 %i to float 292 %r = fpext float %x to double 293 ret double %r 294} 295 296; Negative test - intermediate rounding in float type. 297 298define double @ItoFtoF_u25_f32_f64(i25 %i) { 299; CHECK-LABEL: @ItoFtoF_u25_f32_f64( 300; CHECK-NEXT: [[X:%.*]] = uitofp i25 [[I:%.*]] to float 301; CHECK-NEXT: [[R:%.*]] = fpext float [[X]] to double 302; CHECK-NEXT: ret double [[R]] 303; 304 %x = uitofp i25 %i to float 305 %r = fpext float %x to double 306 ret double %r 307} 308 309; UB on overflow guarantees that the input is small enough to fit in i32. 310 311define double @FtoItoFtoF_f32_s32_f32_f64(float %f) { 312; CHECK-LABEL: @FtoItoFtoF_f32_s32_f32_f64( 313; CHECK-NEXT: [[I:%.*]] = fptosi float [[F:%.*]] to i32 314; CHECK-NEXT: [[R:%.*]] = sitofp i32 [[I]] to double 315; CHECK-NEXT: ret double [[R]] 316; 317 %i = fptosi float %f to i32 318 %x = sitofp i32 %i to float 319 %r = fpext float %x to double 320 ret double %r 321} 322 323declare void @use_i32(i32) 324declare void @use_f32(float) 325 326; Extra uses are ok; unsigned is ok. 327 328define double @FtoItoFtoF_f32_u32_f32_f64_extra_uses(float %f) { 329; CHECK-LABEL: @FtoItoFtoF_f32_u32_f32_f64_extra_uses( 330; CHECK-NEXT: [[I:%.*]] = fptoui float [[F:%.*]] to i32 331; CHECK-NEXT: call void @use_i32(i32 [[I]]) 332; CHECK-NEXT: [[X:%.*]] = uitofp i32 [[I]] to float 333; CHECK-NEXT: call void @use_f32(float [[X]]) 334; CHECK-NEXT: [[R:%.*]] = uitofp i32 [[I]] to double 335; CHECK-NEXT: ret double [[R]] 336; 337 %i = fptoui float %f to i32 338 call void @use_i32(i32 %i) 339 %x = uitofp i32 %i to float 340 call void @use_f32(float %x) 341 %r = fpext float %x to double 342 ret double %r 343} 344 345; Vectors are ok; initial type can be smaller than intermediate type. 346 347define <3 x double> @FtoItoFtoF_v3f16_v3s32_v3f32_v3f64(<3 x half> %f) { 348; CHECK-LABEL: @FtoItoFtoF_v3f16_v3s32_v3f32_v3f64( 349; CHECK-NEXT: [[I:%.*]] = fptosi <3 x half> [[F:%.*]] to <3 x i32> 350; CHECK-NEXT: [[R:%.*]] = sitofp <3 x i32> [[I]] to <3 x double> 351; CHECK-NEXT: ret <3 x double> [[R]] 352; 353 %i = fptosi <3 x half> %f to <3 x i32> 354 %x = sitofp <3 x i32> %i to <3 x float> 355 %r = fpext <3 x float> %x to <3 x double> 356 ret <3 x double> %r 357} 358 359; Wider than double is ok. 360 361define fp128 @FtoItoFtoF_f32_s64_f64_f128(float %f) { 362; CHECK-LABEL: @FtoItoFtoF_f32_s64_f64_f128( 363; CHECK-NEXT: [[I:%.*]] = fptosi float [[F:%.*]] to i64 364; CHECK-NEXT: [[R:%.*]] = sitofp i64 [[I]] to fp128 365; CHECK-NEXT: ret fp128 [[R]] 366; 367 %i = fptosi float %f to i64 368 %x = sitofp i64 %i to double 369 %r = fpext double %x to fp128 370 ret fp128 %r 371} 372 373; Target-specific type is ok. 374 375define x86_fp80 @FtoItoFtoF_f64_u54_f64_f80(double %f) { 376; CHECK-LABEL: @FtoItoFtoF_f64_u54_f64_f80( 377; CHECK-NEXT: [[I:%.*]] = fptoui double [[F:%.*]] to i54 378; CHECK-NEXT: [[R:%.*]] = uitofp i54 [[I]] to x86_fp80 379; CHECK-NEXT: ret x86_fp80 [[R]] 380; 381 %i = fptoui double %f to i54 382 %x = uitofp i54 %i to double 383 %r = fpext double %x to x86_fp80 384 ret x86_fp80 %r 385} 386 387; Weird target-specific type is ok (not possible to extend *from* that type). 388 389define ppc_fp128 @FtoItoFtoF_f64_u54_f64_p128(double %f) { 390; CHECK-LABEL: @FtoItoFtoF_f64_u54_f64_p128( 391; CHECK-NEXT: [[I:%.*]] = fptoui double [[F:%.*]] to i54 392; CHECK-NEXT: [[R:%.*]] = uitofp i54 [[I]] to ppc_fp128 393; CHECK-NEXT: ret ppc_fp128 [[R]] 394; 395 %i = fptoui double %f to i54 396 %x = uitofp i54 %i to double 397 %r = fpext double %x to ppc_fp128 398 ret ppc_fp128 %r 399} 400 401; Unsigned to signed is ok because signed int has smaller magnitude. 402 403define double @FtoItoFtoF_f32_us32_f32_f64(float %f) { 404; CHECK-LABEL: @FtoItoFtoF_f32_us32_f32_f64( 405; CHECK-NEXT: [[I:%.*]] = fptoui float [[F:%.*]] to i32 406; CHECK-NEXT: [[R:%.*]] = sitofp i32 [[I]] to double 407; CHECK-NEXT: ret double [[R]] 408; 409 %i = fptoui float %f to i32 410 %x = sitofp i32 %i to float 411 %r = fpext float %x to double 412 ret double %r 413} 414 415; Negative test: consider -1.0 416 417define double @FtoItoFtoF_f32_su32_f32_f64(float %f) { 418; CHECK-LABEL: @FtoItoFtoF_f32_su32_f32_f64( 419; CHECK-NEXT: [[I:%.*]] = fptosi float [[F:%.*]] to i32 420; CHECK-NEXT: [[X:%.*]] = uitofp i32 [[I]] to float 421; CHECK-NEXT: [[R:%.*]] = fpext float [[X]] to double 422; CHECK-NEXT: ret double [[R]] 423; 424 %i = fptosi float %f to i32 425 %x = uitofp i32 %i to float 426 %r = fpext float %x to double 427 ret double %r 428} 429 430define half @bf16_to_f32_to_f16(bfloat %a) nounwind { 431; CHECK-LABEL: @bf16_to_f32_to_f16( 432; CHECK-NEXT: [[Y:%.*]] = fpext bfloat [[A:%.*]] to float 433; CHECK-NEXT: [[Z:%.*]] = fptrunc float [[Y]] to half 434; CHECK-NEXT: ret half [[Z]] 435; 436 %y = fpext bfloat %a to float 437 %z = fptrunc float %y to half 438 ret half %z 439} 440 441define bfloat @bf16_frem(bfloat %x) { 442; CHECK-LABEL: @bf16_frem( 443; CHECK-NEXT: [[TMP1:%.*]] = frem bfloat [[X:%.*]], 0xR40C9 444; CHECK-NEXT: ret bfloat [[TMP1]] 445; 446 %t1 = fpext bfloat %x to float 447 %t2 = frem float %t1, 6.281250e+00 448 %t3 = fptrunc float %t2 to bfloat 449 ret bfloat %t3 450} 451